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

Annotation of /trunk/models/dyn_flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations) (download) (as text)
Fri Oct 29 20:54:12 2004 UTC (19 years, 7 months ago) by aw0a
File MIME type: text/x-ascend
File size: 62025 byte(s)
Setting up web subdirectory in repository
1 aw0a 1 REQUIRE "ivpsystem.a4l";
2     REQUIRE "splitter.a4l";
3     (* => splitter.a4l, stream_holdup.a4l thermodynamics.a4l, components.a4l,
4     * phases.a4l, atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *)
5     PROVIDE "dyn_flash.a4l";
6    
7     (*
8     * dyn_flash.a4l
9     * by Duncan Coffey
10     * Modified from flash.a4l by Ben Allan
11     * Part of the ASCEND Library
12     * $Date: 1998/06/20 15:12:02 $
13     * $Revision: 1.3 $
14     * $Author: ballan $
15     * $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/dyn_flash.a4l,v $
16     *
17     * This file is part of the ASCEND Modeling Library.
18     * The file provide basic vapor-liquid equilibrium flash calcuations
19     * in various unit operation configurations.
20     *
21     * Copyright (C) 1998 Carnegie Mellon University
22     *
23     * The ASCEND Modeling Library is free software; you can redistribute
24     * it and/or modify it under the terms of the GNU General Public
25     * License as published by the Free Software Foundation; either
26     * version 2 of the License, or (at your option) any later version.
27     *
28     * The ASCEND Modeling Library is distributed in hope that it
29     * will be useful, but WITHOUT ANY WARRANTY; without even the implied
30     * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
31     * See the GNU General Public License for more details.
32     *
33     * You should have received a copy of the GNU General Public License
34     * along with the program; if not, write to the Free Software
35     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check
36     * the file named COPYING.
37     *)
38    
39     MODEL flash_base(
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
46     make type tree navigation easier.
47     }
48     'purpose' SELF {
49     This library provides models:
50     vapor_liquid_flash - a simple two product flash of an arbitrary feed.
51     simple_reboiler - a reboiler with "stream" connections for use in columns.
52     total_condenser - a total condenser with "stream" connections for use in columns.
53     tray - a tray with "stream" connections for use in columns.
54     feed_tray - a feed tray with "stream" connections for use in columns.
55     detailed_tray - a tray with "detailed_stream" connections for use in stacks.
56     }
57     END NOTES;
58     END flash_base;
59    
60     MODEL vapor_liquid_flash(
61     feed WILL_BE stream;
62     vapout WILL_BE stream;
63     liqout WILL_BE stream;
64     t WILL_BE time;
65     dynamic WILL_BE boolean;
66     ode_offset WILL_BE ode_counter;
67     obs_offset WILL_BE obs_counter;
68     ) WHERE (
69     feed, vapout, liqout WILL_NOT_BE_THE_SAME;
70     feed.cd, vapout.cd, liqout.cd WILL_BE_THE_SAME;
71     vapout.pd.phase_indicator == 'V';
72     liqout.pd.phase_indicator == 'L';
73     (feed.pd.phase_indicator IN ['V','L','VL','VLL']) == TRUE;
74     ) REFINES flash_base;
75    
76     NOTES
77     'purpose' SELF {
78     This MODEL computes a VL flash with the potential that the whole
79     feed subcools or superheats into one or the other product.
80     The user supplies all streams, time, a dynamic boolean and obs and ode
81     counters.
82     If equilibrated is TRUE, V-L equilibrium will be
83     attempted, otherwise the unit will solve only the mass balances
84     and single phase properties.
85     }
86     'developer-Duncan' SELF {
87     This is a simple dynamic model of a flash unit. The user creates a
88     vapor product, a liquid product, and any
89     feed and gives them to us with time, a dynamic boolean and ode and obs
90     counters. We do the assembly of the flash VLE MODEL from
91     the given output stream states.
92     }
93     END NOTES;
94    
95     cd ALIASES feed.cd;
96     P ALIASES liqout.P;
97     T ALIASES liqout.T;
98     equilibrated ALIASES vapout.equilibrated;
99     (* flash thermo options are derived from product streams *)
100     pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
101     liqout.pd.liquid1_option, 'none');
102    
103     (* flash Vapor-Liquid state comes from thermo of product streams. *)
104     phaseVL[VLphases] ALIASES
105     (vapout.phase['vapor'], liqout.phase['liquid1'])
106     WHERE VLphases IS_A set OF symbol_constant
107     WITH_VALUE ('vapor','liquid1');
108     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
109    
110     x "liquid product composition" ALIASES liqout.state.y;
111     y "vapor product composition" ALIASES vapout.state.y;
112    
113    
114     dMi_dt[cd.other_components] IS_A molar_rate;
115     M "total mass holdup",
116     Mi[cd.components] "species holdup",
117     Ml "liquid mass holdup",
118     Mv "vapor mass holdup" IS_A mole;
119     dM_dt IS_A molar_rate;
120     dU_dt IS_A energy_rate;
121     U "internal energy holdup" IS_A energy;
122     Vol "holdup volume",
123     vol_liq "holdup liquid volume",
124     vol_vap "holdup vapor volume" IS_A volume;
125     Qin "heat input" IS_A energy_rate;
126     split_fraction[VLphases] IS_A fraction;
127     flowscale IS_A molar_rate_scale;
128    
129     (* component material balances *)
130     FOR i IN cd.other_components CREATE
131     cmb[i]:
132     dMi_dt[i]/flowscale =
133     (feed.f[i] - vapout.f[i] - liqout.f[i]) / flowscale;
134     END FOR;
135    
136     (* overall material balance *)
137     OMB:
138     dM_dt/flowscale = (feed.flow - vapout.flow - liqout.flow)/flowscale;
139    
140     vapor_balance: (vapout.flow -
141     split_fraction['vapor'] * feed.flow)/flowscale = 0;
142    
143     SUM[split_fraction[i] | i IN VLphases] = 1;
144    
145     state.phase_fraction['vapor'] * M = Mv;
146    
147     FOR i IN cd.components CREATE
148     Mi[i] = Ml*x[i] + Mv*y[i];
149     END FOR;
150     M = Ml + Mv;
151     Vol = vol_liq + vol_vap;
152     vol_liq = Ml * state.phase['liquid1'].v_y;
153     vol_vap = Mv * state.phase['vapor'].v_y;
154    
155     (* overall energy balance *)
156     H_flowscale IS_A energy_rate_scale;
157    
158     dU_dt/H_flowscale =
159     (feed.H_flow + Qin - vapout.H_flow - liqout.H_flow)/H_flowscale;
160    
161     U/H_flowscale =
162     (state.phase['vapor'].h_y * Mv + state.phase['liquid1'].h_y * Ml)
163     /H_flowscale;
164    
165     boundwidth IS_A bound_width;
166    
167     METHODS
168    
169     METHOD check_self;
170     IF (liqout.flow < 1e-4 {mole/s}) THEN
171     STOP {Liquid flow dried up in flash};
172     END IF;
173     IF (vapout.flow < 1e-4 {mole/s}) THEN
174     STOP {All vapor condensed in flash};
175     END IF;
176     IF (feed.flow < 1e-4 {mole/s}) THEN
177     STOP {No feed flowing to flash};
178     END IF;
179     IF (abs(feed.flow - vapout.flow - liqout.flow)/flowscale > 1.0e-4) THEN
180     STOP {Flash violates overall mass-balance};
181     END IF;
182     RUN pdVL.check_self;
183     RUN state.check_self;
184     END check_self;
185    
186     METHOD check_all;
187     RUN feed.check_self;
188     RUN vapout.check_self;
189     RUN liqout.check_self;
190     RUN check_self;
191     END check_all;
192    
193     METHOD default_self;
194     boundwidth :=10;
195     flowscale := feed.Details.flowscale;
196     H_flowscale := feed.Details.H_flowscale;
197     dMi_dt[cd.other_components] :=0 {mole/sec};
198     dMi_dt[cd.other_components].lower_bound :=-1e100 {mole/sec};
199     dM_dt :=0 {mole/sec};
200     dM_dt.lower_bound :=-1e100 {mole/sec};
201     dU_dt :=0 {J/sec};
202     (* Upper bound of split fraction must be changed to
203     greater than 1 for dynamic simulation *)
204     split_fraction[VLphases].upper_bound :=2;
205     split_fraction[VLphases].lower_bound :=-2;
206     dynamic :=FALSE;
207     t :=0 {s};
208     RUN pdVL.default_self;
209     RUN state.default_self;
210     END default_self;
211    
212     METHOD default_all;
213     Qin := 0 {watt};
214     RUN feed.default_self;
215     RUN vapout.default_self;
216     RUN liqout.default_self;
217     RUN default_self;
218     END default_all;
219    
220     METHOD bound_self;
221     state.boundwidth := boundwidth;
222     RUN pdVL.bound_self;
223     RUN state.bound_self;
224     END bound_self;
225    
226     METHOD bound_all;
227     feed.boundwidth := boundwidth;
228     vapout.boundwidth := boundwidth;
229     liqout.boundwidth := boundwidth;
230     RUN feed.bound_self;
231     RUN vapout.bound_self;
232     RUN liqout.bound_self;
233     RUN bound_self;
234     END bound_all;
235    
236     METHOD scale_self;
237     flowscale := feed.flow;
238     H_flowscale := feed.H_flow;
239     RUN pdVL.scale_self;
240     RUN state.scale_self;
241     END scale_self;
242    
243     METHOD scale_all;
244     RUN feed.scale_self;
245     RUN vapout.scale_self;
246     RUN liqout.scale_self;
247     RUN scale_self;
248     END scale_all;
249    
250     METHOD seqmod;
251     RUN state.specify;
252     state.y[cd.components].fixed := FALSE;
253     IF equilibrated THEN
254     state.T.fixed :=FALSE;
255     ELSE
256     state.T.fixed :=TRUE;
257     END IF;
258     split_fraction['vapor'].fixed :=TRUE;
259     state.phase_fraction['vapor'].fixed :=FALSE;
260     dMi_dt[cd.other_components].fixed :=TRUE;
261     Mi[cd.components].fixed :=FALSE;
262     dM_dt.fixed :=TRUE;
263     M.fixed :=FALSE;
264     dU_dt.fixed :=TRUE;
265     U.fixed :=FALSE;
266     Vol.fixed :=TRUE;
267     vol_liq.fixed :=TRUE;
268     IF dynamic THEN
269     dMi_dt[cd.other_components].fixed :=FALSE;
270     Mi[cd.other_components].fixed :=TRUE;
271     dM_dt.fixed :=FALSE;
272     M.fixed :=TRUE;
273     dU_dt.fixed :=FALSE;
274     U.fixed :=TRUE;
275     Qin.fixed :=TRUE;
276     IF equilibrated THEN
277     state.P.fixed :=FALSE;
278     ELSE
279     state.T.fixed :=FALSE;
280     END IF;
281     vol_liq.fixed :=FALSE;
282     liqout.flow.fixed :=TRUE;
283     vapout.flow.fixed :=TRUE;
284     split_fraction['vapor'].fixed :=FALSE;
285     ELSE
286     dMi_dt[cd.other_components] :=0 {mole/sec};
287     dM_dt :=0 {mole/sec};
288     dU_dt :=0 {J/sec};
289     END IF;
290     END seqmod;
291    
292     METHOD specify;
293     RUN feed.specify;
294     RUN seqmod;
295     END specify;
296    
297     METHOD set_ode;
298     t.ode_type :=-1;
299     FOR i IN cd.other_components DO
300     dMi_dt[i].ode_type :=2;
301     Mi[i].ode_type :=1;
302     dMi_dt[i].ode_id :=ode_offset;
303     Mi[i].ode_id :=ode_offset;
304     ode_offset :=ode_offset+1;
305     END FOR;
306     dM_dt.ode_type :=2;
307     M.ode_type :=1;
308     dM_dt.ode_id :=ode_offset;
309     M.ode_id :=ode_offset;
310     ode_offset :=ode_offset+1;
311     dU_dt.ode_type :=2;
312     U.ode_type :=1;
313     dU_dt.ode_id :=ode_offset;
314     U.ode_id :=ode_offset;
315     ode_offset :=ode_offset+1;
316     END set_ode;
317    
318     METHOD set_obs;
319     Vol.obs_id :=obs_offset;
320     vol_liq.obs_id :=obs_offset+1;
321     state.T.obs_id :=obs_offset+2;
322     state.P.obs_id :=obs_offset+3;
323     Qin.obs_id :=obs_offset+4;
324     feed.flow.obs_id :=obs_offset+5;
325     liqout.flow.obs_id :=obs_offset+6;
326     vapout.flow.obs_id :=obs_offset+7;
327     obs_offset :=obs_offset+8;
328     END set_obs;
329     END vapor_liquid_flash;
330    
331     MODEL tray_base(
332    
333     ) REFINES flash_base;
334     END tray_base;
335    
336     MODEL detailed_tray(
337     liqin WILL_BE detailed_stream;
338     vapin WILL_BE detailed_stream;
339     liqout WILL_BE detailed_stream;
340     vapout WILL_BE detailed_stream;
341     state WILL_BE thermodynamics;
342     t WILL_BE time;
343     dynamic WILL_BE boolean;
344     ode_offset WILL_BE ode_counter;
345     obs_offset WILL_BE obs_counter;
346     ) WHERE (
347     liqout.state, vapout.state WILL_NOT_BE_THE_SAME;
348     vapin.state.cd, vapout.state.cd WILL_BE_THE_SAME;
349     vapin.state.pd.phase_indicator == 'V';
350     liqin.state.pd.phase_indicator == 'L';
351     vapout.state.pd.phase_indicator == 'V';
352     liqout.state.pd.phase_indicator == 'L';
353     ) REFINES tray_base;
354    
355     NOTES
356     'purpose' SELF {
357     This MODEL computes VLE for a tray with the purpose of being used in a
358     stack of trays for a column. The streams used are detailed_streams
359     which make it easier to construct a stack of trays with a lot less variables.
360     The user supplies all streams, time, a dynamic boolean and obs and ode
361     counters.
362     If equilibrated is TRUE, V-L equilibrium will be
363     attempted, OTHERWISE the unit will solve only the mass balances.
364     }
365     'developer-Duncan' SELF {
366     This is a simple dynamic model of a tray. The user creates a
367     vapor feed and product, a liquid feed and product, along with time,
368     a dynamic boolean and ode and obs counters. We do the assembly of the
369     tray VLE MODEL from the given output stream states.
370     }
371     END NOTES;
372    
373     cd ALIASES vapout.state.cd;
374     P ALIASES liqout.P;
375     T ALIASES liqout.T;
376     equilibrated ALIASES vapout.state.equilibrated;
377     x "liquid product composition" ALIASES liqout.state.y;
378     y "vapor product composition" ALIASES vapout.state.y;
379    
380    
381     dMi_dt[cd.other_components] IS_A molar_rate;
382     M,Mi[cd.components],Ml,Mv IS_A mole;
383     dM_dt IS_A molar_rate;
384     dU_dt IS_A energy_rate;
385     U IS_A energy;
386     Vol,vol_liq,vol_vap IS_A volume;
387     Qin IS_A energy_rate;
388     flowscale IS_A molar_rate_scale;
389     cmo_ratio "Constant molar overflow" IS_A factor;
390    
391     cmo_eqn: (cmo_ratio * liqin.flow - liqout.flow)/flowscale = 0;
392    
393     (* component material balances *)
394     FOR i IN cd.other_components CREATE
395     dMi_dt[i]/flowscale=(liqin.f[i]+vapin.f[i]-vapout.f[i]-liqout.f[i])/flowscale;
396     END FOR;
397     (* overall material balance *)
398     dM_dt/flowscale=(liqin.flow+vapin.flow-vapout.flow-liqout.flow)/flowscale;
399    
400     FOR i IN cd.components CREATE
401     Mi[i]=Ml*x[i]+Mv*y[i];
402     END FOR;
403     M=Ml+Mv;
404     Vol=vol_liq+vol_vap;
405     vol_liq=Ml*state.phase['liquid1'].v_y;
406     vol_vap=Mv*state.phase['vapor'].v_y;
407    
408     state.phase_fraction['vapor'] * M = Mv;
409    
410     (* hydraulic type equations *)
411     taul,tauv IS_A time;
412    
413     taul*liqout.flow = Ml;
414     tauv*vapout.flow = sqrt(state.P/1{Pa})*1{mol};
415    
416    
417     (* overall energy balance *)
418     H_flowscale IS_A energy_rate_scale;
419    
420     dU_dt/H_flowscale=(liqin.H_flow+vapin.H_flow+Qin-vapout.H_flow
421     -liqout.H_flow)/H_flowscale;
422    
423     U/H_flowscale = (state.phase['vapor'].h_y*Mv+state.phase['liquid1'].h_y*Ml)
424     /H_flowscale;
425     boundwidth IS_A bound_width;
426     METHODS
427     METHOD check_self;
428     IF (liqout.flow < 1e-4 {mole/s}) THEN
429     STOP {Liquid flow dried up in tray};
430     END IF;
431     IF (vapout.flow < 1e-4 {mole/s}) THEN
432     STOP {All vapor condensed in tray};
433     END IF;
434     IF (vapin.flow < 1e-4 {mole/s}) THEN
435     STOP {No vapin flowing to tray};
436     END IF;
437     IF (liqin.flow < 1e-4 {mole/s}) THEN
438     STOP {No liqin flowing to tray};
439     END IF;
440     IF (abs(vapin.flow+liqin.flow - vapout.flow - liqout.flow)
441     /flowscale > 1.0e-4) THEN
442     STOP {tray violates overall mass-balance};
443     END IF;
444     RUN state.check_self;
445     END check_self;
446    
447     METHOD check_all;
448     RUN vapin.check_self;
449     RUN liqin.check_self;
450     RUN vapout.check_self;
451     RUN liqout.check_self;
452     RUN state.check_self;
453     RUN check_self;
454     END check_all;
455    
456     METHOD default_self;
457     boundwidth :=10;
458     flowscale := vapout.flowscale;
459     H_flowscale := vapout.H_flowscale;
460     dMi_dt[cd.other_components] :=0 {mole/sec};
461     dMi_dt[cd.other_components].lower_bound :=-1e100 {mole/sec};
462     dM_dt :=0 {mole/sec};
463     dM_dt.lower_bound :=-1e100 {mole/sec};
464     dU_dt :=0 {J/sec};
465     dynamic :=FALSE;
466     t :=0 {s};
467     END default_self;
468    
469     METHOD default_all;
470     Qin := 0 {watt};
471     RUN vapin.default_self;
472     RUN liqin.default_self;
473     RUN vapout.default_self;
474     RUN liqout.default_self;
475     RUN state.default_self;
476     RUN default_self;
477     END default_all;
478    
479     METHOD bound_self;
480     state.boundwidth := boundwidth;
481     END bound_self;
482    
483     METHOD bound_all;
484     vapin.boundwidth := boundwidth;
485     liqin.boundwidth := boundwidth;
486     vapout.boundwidth := boundwidth;
487     liqout.boundwidth := boundwidth;
488     RUN vapin.bound_self;
489     RUN liqin.bound_self;
490     RUN vapout.bound_self;
491     RUN liqout.bound_self;
492     RUN state.bound_self;
493     RUN bound_self;
494     END bound_all;
495    
496     METHOD scale_self;
497     flowscale := vapin.flow;
498     H_flowscale := vapin.H_flow;
499     END scale_self;
500    
501     METHOD scale_all;
502     RUN vapin.scale_self;
503     RUN liqin.scale_self;
504     RUN vapout.scale_self;
505     RUN liqout.scale_self;
506     RUN state.scale_self;
507     RUN scale_self;
508     END scale_all;
509    
510     METHOD seqmod;
511     RUN state.specify;
512     state.y[cd.components].fixed := FALSE;
513     IF equilibrated THEN
514     state.T.fixed :=FALSE;
515     ELSE
516     state.T.fixed :=TRUE;
517     END IF;
518     state.phase_fraction['vapor'].fixed :=FALSE;
519     cmo_ratio.fixed :=TRUE;
520     dMi_dt[cd.other_components].fixed :=TRUE;
521     Mi[cd.other_components].fixed :=FALSE;
522     dM_dt.fixed :=TRUE;
523     M.fixed :=FALSE;
524     dU_dt.fixed :=TRUE;
525     U.fixed :=FALSE;
526     Vol.fixed :=TRUE;
527     vol_liq.fixed :=TRUE;
528     tauv.fixed :=FALSE;
529     taul.fixed :=FALSE;
530     liqout.flow.fixed :=FALSE;
531     vapout.flow.fixed :=FALSE;
532     IF dynamic THEN
533     dMi_dt[cd.other_components].fixed :=FALSE;
534     Mi[cd.other_components].fixed :=TRUE;
535     dM_dt.fixed :=FALSE;
536     M.fixed :=TRUE;
537     dU_dt.fixed :=FALSE;
538     U.fixed :=TRUE;
539     Qin.fixed :=TRUE;
540     IF equilibrated THEN
541     state.P.fixed :=FALSE;
542     ELSE
543     state.T.fixed :=FALSE;
544     END IF;
545     vol_liq.fixed :=FALSE;
546     tauv.fixed :=TRUE;
547     taul.fixed :=TRUE;
548     cmo_ratio.fixed :=FALSE;
549     ELSE
550     dMi_dt[cd.other_components] :=0 {mole/sec};
551     dM_dt :=0 {mole/sec};
552     dU_dt :=0 {J/sec};
553     END IF;
554     END seqmod;
555    
556     METHOD specify;
557     RUN vapin.specify;
558     RUN liqin.specify;
559     RUN seqmod;
560     END specify;
561    
562     METHOD reset_to_adiabatic;
563     cmo_ratio.fixed := FALSE;
564     Qin.fixed := TRUE;
565     Qin := 0{W};
566     END reset_to_adiabatic;
567    
568     METHOD set_ode;
569     t.ode_type :=-1;
570     FOR i IN cd.other_components DO
571     dMi_dt[i].ode_type :=2;
572     Mi[i].ode_type :=1;
573     dMi_dt[i].ode_id :=ode_offset;
574     Mi[i].ode_id :=ode_offset;
575     ode_offset :=ode_offset+1;
576     END FOR;
577     dM_dt.ode_type :=2;
578     M.ode_type :=1;
579     dM_dt.ode_id :=ode_offset;
580     M.ode_id :=ode_offset;
581     ode_offset :=ode_offset+1;
582     dU_dt.ode_type :=2;
583     U.ode_type :=1;
584     dU_dt.ode_id :=ode_offset;
585     U.ode_id :=ode_offset;
586     ode_offset :=ode_offset+1;
587     END set_ode;
588     METHOD set_obs;
589     Vol.obs_id :=obs_offset;
590     vol_liq.obs_id :=obs_offset+1;
591     state.T.obs_id :=obs_offset+2;
592     state.P.obs_id :=obs_offset+3;
593     Qin.obs_id :=obs_offset+4;
594     vapin.flow.obs_id :=obs_offset+5;
595     liqin.flow.obs_id :=obs_offset+6;
596     liqout.flow.obs_id :=obs_offset+7;
597     vapout.flow.obs_id :=obs_offset+8;
598     obs_offset :=obs_offset+9;
599     END set_obs;
600     END detailed_tray;
601    
602    
603     MODEL tray(
604     liqin WILL_BE stream;
605     vapin WILL_BE stream;
606     liqout WILL_BE stream;
607     vapout WILL_BE stream;
608     t WILL_BE time;
609     dynamic WILL_BE boolean;
610     ode_offset WILL_BE ode_counter;
611     obs_offset WILL_BE obs_counter;
612     ) WHERE (
613     liqout.state, vapout.state WILL_NOT_BE_THE_SAME;
614     vapin.state.cd, vapout.state.cd WILL_BE_THE_SAME;
615     vapin.pd.phase_indicator == 'V';
616     liqin.pd.phase_indicator == 'L';
617     vapout.pd.phase_indicator == 'V';
618     liqout.pd.phase_indicator == 'L';
619     ) REFINES tray_base;
620     NOTES
621     'purpose' SELF {
622     This MODEL uses the detailed_tray model create a tray using streams
623     instead of detailed streams.
624     The user supplies all streams, time, a dynamic boolean and obs and ode
625     counters.
626     If equilibrated is TRUE, V-L equilibrium will be
627     attempted, OTHERWISE the unit will solve only the mass balances.
628     }
629     'developer-Duncan' SELF {
630     This is a simple dynamic model of a tray. The user creates a
631     vapor feed and product, a liquid feed and product, along with time,
632     a dynamic boolean and ode and obs counters. We do the assembly of the
633     tray VLE MODEL from the given output stream states.
634     }
635     END NOTES;
636     cd ALIASES vapout.cd;
637     P ALIASES liqout.P;
638     T ALIASES liqout.T;
639     equilibrated ALIASES vapout.equilibrated;
640     pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
641     liqout.pd.liquid1_option, 'none');
642    
643     phaseVL[VLphases] ALIASES
644     (vapout.phase['vapor'], liqout.phase['liquid1'])
645     WHERE VLphases IS_A set OF symbol_constant
646     WITH_VALUE ('vapor','liquid1');
647    
648     state IS_A thermodynamics(cd,pdVL,phaseVL,equilibrated);
649    
650     details IS_A detailed_tray(liqin.Details,vapin.Details,liqout.Details,vapout.Details,
651     state,t,dynamic,ode_offset,obs_offset);
652    
653     Vol ALIASES details.Vol;
654     vol_liq ALIASES details.vol_liq;
655     vol_vap ALIASES details.vol_vap;
656     Qin ALIASES details.Qin;
657     cmo_ratio ALIASES details.cmo_ratio;
658    
659     METHODS
660     METHOD check_self;
661     IF (liqout.flow < 1e-4 {mole/s}) THEN
662     STOP {Liquid flow dried up in tray};
663     END IF;
664     IF (vapout.flow < 1e-4 {mole/s}) THEN
665     STOP {All vapor condensed in tray};
666     END IF;
667     IF (vapin.flow < 1e-4 {mole/s}) THEN
668     STOP {No vapin flowing to tray};
669     END IF;
670     IF (liqin.flow < 1e-4 {mole/s}) THEN
671     STOP {No liqin flowing to tray};
672     END IF;
673     IF (abs(vapin.flow+liqin.flow - vapout.flow - liqout.flow)
674     > 1.0e-4) THEN
675     STOP {tray violates overall mass-balance};
676     END IF;
677     RUN details.check_self;
678     END check_self;
679    
680     METHOD check_all;
681     RUN vapin.check_self;
682     RUN liqin.check_self;
683     RUN vapout.check_self;
684     RUN liqout.check_self;
685     RUN check_self;
686     END check_all;
687    
688     METHOD default_self;
689     dynamic :=FALSE;
690     t :=0 {s};
691     RUN pdVL.default_self;
692     RUN state.default_self;
693     RUN details.default_self;
694     END default_self;
695    
696     METHOD default_all;
697     RUN vapin.default_self;
698     RUN liqin.default_self;
699     RUN vapout.default_self;
700     RUN liqout.default_self;
701     RUN default_self;
702     END default_all;
703    
704     METHOD bound_self;
705     RUN pdVL.bound_self;
706     RUN state.bound_self;
707     RUN details.bound_self;
708     END bound_self;
709    
710     METHOD bound_all;
711     RUN vapin.bound_self;
712     RUN liqin.bound_self;
713     RUN vapout.bound_self;
714     RUN liqout.bound_self;
715     RUN bound_self;
716     END bound_all;
717    
718     METHOD scale_self;
719     RUN pdVL.scale_self;
720     RUN state.scale_self;
721     RUN details.scale_self;
722     END scale_self;
723    
724     METHOD scale_all;
725     RUN vapin.scale_self;
726     RUN liqin.scale_self;
727     RUN vapout.scale_self;
728     RUN liqout.scale_self;
729     RUN scale_self;
730     END scale_all;
731    
732     METHOD seqmod;
733     RUN details.seqmod;
734     END seqmod;
735    
736     METHOD specify;
737     RUN details.specify;
738     END specify;
739    
740     METHOD reset_to_adiabatic;
741     RUN details.reset_to_adiabatic;
742     END reset_to_adiabatic;
743    
744     METHOD set_ode;
745     RUN details.set_ode;
746     END set_ode;
747     METHOD set_obs;
748     RUN details.set_obs;
749     END set_obs;
750     END tray;
751    
752     MODEL feed_tray(
753     feed WILL_BE stream;
754     liqin WILL_BE stream;
755     vapin WILL_BE stream;
756     liqout WILL_BE stream;
757     vapout WILL_BE stream;
758     t WILL_BE time;
759     dynamic WILL_BE boolean;
760     ode_offset WILL_BE ode_counter;
761     obs_offset WILL_BE obs_counter;
762     ) WHERE (
763     feed.state, liqout.state, vapout.state WILL_NOT_BE_THE_SAME;
764     feed.cd, vapin.state.cd, vapout.state.cd WILL_BE_THE_SAME;
765     (feed.pd.phase_indicator IN ['V','L','VL','VLL']) == TRUE;
766     vapin.pd.phase_indicator == 'V';
767     liqin.pd.phase_indicator == 'L';
768     vapout.pd.phase_indicator == 'V';
769     liqout.pd.phase_indicator == 'L';
770     ) REFINES tray_base;
771     NOTES
772     'purpose' SELF {
773     This MODEL is the same as a tray except it has an extra input
774     stream and the equations are written instead of created by
775     detailed+tray. This model would be used as a feed tray in a column
776     model.
777     The user supplies all streams, time, a dynamic boolean and obs and ode
778     counters.
779     If equilibrated is TRUE, V-L equilibrium will be
780     attempted, OTHERWISE the unit will solve only the mass balances.
781     }
782     'developer-Duncan' SELF {
783     This is a simple dynamic model of a feed_tray. The user creates a
784     vapor feed and product, a liquid feed and product, just like a normal
785     tray but also has to create another feed, along with time,
786     a dynamic boolean and ode and obs counters. We do the assembly of the
787     tray VLE MODEL from the given output stream states.
788     }
789     END NOTES;
790     cd ALIASES feed.cd;
791     P ALIASES liqout.P;
792     T ALIASES liqout.T;
793     equilibrated ALIASES vapout.equilibrated;
794     (* flash thermo options are derived from product streams *)
795     pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
796     liqout.pd.liquid1_option, 'none');
797    
798     (* flash Vapor-Liquid state comes from thermo of product streams. *)
799     phaseVL[VLphases] ALIASES
800     (vapout.phase['vapor'], liqout.phase['liquid1'])
801     WHERE VLphases IS_A set OF symbol_constant
802     WITH_VALUE ('vapor','liquid1');
803     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
804    
805     x "liquid product composition" ALIASES liqout.state.y;
806     y "vapor product composition" ALIASES vapout.state.y;
807    
808    
809     dMi_dt[cd.other_components] IS_A molar_rate;
810     M,Mi[cd.components],Ml,Mv IS_A mole;
811     dM_dt,dMl_dt,dMv_dt IS_A molar_rate;
812     dU_dt IS_A energy_rate;
813     U IS_A energy;
814     Vol,vol_liq,vol_vap IS_A volume;
815     Qin IS_A energy_rate;
816     flowscale IS_A molar_rate_scale;
817     q IS_A factor;
818    
819     q_eqn: (liqout.flow - (liqin.flow + q * feed.flow)) / flowscale = 0;
820    
821     (* component material balances *)
822     FOR i IN cd.other_components CREATE
823     cmb[i]:
824     dMi_dt[i]/flowscale=(feed.f[i]+liqin.f[i]+vapin.f[i]-vapout.f[i]
825     -liqout.f[i])/flowscale;
826     END FOR;
827     (* overall material balance *)
828     OMB:
829     dM_dt/flowscale=(feed.flow+liqin.flow+vapin.flow-vapout.flow-liqout.flow)/flowscale;
830    
831     FOR i IN cd.components CREATE
832     phase_cb[i]:
833     Mi[i]=Ml*x[i]+Mv*y[i];
834     END FOR;
835     M=Ml+Mv;
836     Vol=vol_liq+vol_vap;
837     vol_liq=Ml*state.phase['liquid1'].v_y;
838     vol_vap=Mv*state.phase['vapor'].v_y;
839    
840     state.phase_fraction['vapor'] * M = Mv;
841    
842     (* hydraulic type equations *)
843     taul,tauv IS_A time;
844    
845     taul*liqout.flow = Ml;
846     tauv*vapout.flow = sqrt(state.P/1{Pa})*1{mol};
847    
848     (* overall energy balance *)
849    
850     H_flowscale IS_A energy_rate_scale;
851    
852     dU_dt/H_flowscale=(feed.H_flow+liqin.H_flow+vapin.H_flow+Qin-vapout.H_flow
853     -liqout.H_flow)/H_flowscale;
854     U/H_flowscale = (state.phase['vapor'].h_y*Mv+state.phase['liquid1'].h_y*Ml)
855     /H_flowscale;
856    
857     boundwidth IS_A bound_width;
858     METHODS
859     METHOD check_self;
860     IF (feed.flow < 1e-4 {mole/s}) THEN
861     STOP {feed flow dried up in flash};
862     END IF;
863     IF (liqout.flow < 1e-4 {mole/s}) THEN
864     STOP {Liquid flow dried up in flash};
865     END IF;
866     IF (vapout.flow < 1e-4 {mole/s}) THEN
867     STOP {All vapor condensed in flash};
868     END IF;
869     IF (vapin.flow < 1e-4 {mole/s}) THEN
870     STOP {No vapin flowing to flash};
871     END IF;
872     IF (liqin.flow < 1e-4 {mole/s}) THEN
873     STOP {No liqin flowing to flash};
874     END IF;
875     IF (abs(vapin.flow+feed.flow+liqin.flow-vapout.flow-liqout.flow)
876     /flowscale > 1.0e-4) THEN
877     STOP {Feed tray violates overall mass-balance};
878     END IF;
879     RUN pdVL.check_self;
880     RUN state.check_self;
881     END check_self;
882    
883     METHOD check_all;
884     RUN feed.check_self;
885     RUN vapin.check_self;
886     RUN liqin.check_self;
887     RUN vapout.check_self;
888     RUN liqout.check_self;
889     RUN check_self;
890     END check_all;
891    
892     METHOD default_self;
893     boundwidth :=10;
894     flowscale := vapout.Details.flowscale;
895     H_flowscale := vapout.Details.H_flowscale;
896     dMi_dt[cd.other_components] :=0 {mole/sec};
897     dMi_dt[cd.other_components].lower_bound :=-1e100 {mole/sec};
898     dM_dt :=0 {mole/sec};
899     dM_dt.lower_bound :=-1e100 {mole/sec};
900     dU_dt :=0 {J/sec};
901     dynamic :=FALSE;
902     t :=0 {s};
903     RUN pdVL.default_self;
904     RUN state.default_self;
905     END default_self;
906    
907     METHOD default_all;
908     Qin := 0 {watt};
909     RUN feed.default_self;
910     RUN vapin.default_self;
911     RUN liqin.default_self;
912     RUN vapout.default_self;
913     RUN liqout.default_self;
914     RUN default_self;
915     END default_all;
916    
917     METHOD bound_self;
918     state.boundwidth := boundwidth;
919     RUN pdVL.bound_self;
920     RUN state.bound_self;
921     END bound_self;
922    
923     METHOD bound_all;
924     feed.boundwidth := boundwidth;
925     vapin.boundwidth := boundwidth;
926     liqin.boundwidth := boundwidth;
927     vapout.boundwidth := boundwidth;
928     liqout.boundwidth := boundwidth;
929     RUN vapin.bound_self;
930     RUN liqin.bound_self;
931     RUN vapout.bound_self;
932     RUN liqout.bound_self;
933     RUN bound_self;
934     END bound_all;
935    
936     METHOD scale_self;
937     flowscale := vapin.flow;
938     H_flowscale := vapin.H_flow;
939     RUN pdVL.scale_self;
940     RUN state.scale_self;
941     END scale_self;
942    
943     METHOD scale_all;
944     RUN feed.scale_self;
945     RUN vapin.scale_self;
946     RUN liqin.scale_self;
947     RUN vapout.scale_self;
948     RUN liqout.scale_self;
949     RUN scale_self;
950     END scale_all;
951    
952     METHOD seqmod;
953     RUN state.specify;
954     state.y[cd.components].fixed := FALSE;
955     IF equilibrated THEN
956     state.T.fixed :=FALSE;
957     ELSE
958     state.T.fixed :=TRUE;
959     END IF;
960     state.phase_fraction['vapor'].fixed :=FALSE;
961     q.fixed :=TRUE;
962     dMi_dt[cd.other_components].fixed :=TRUE;
963     Mi[cd.other_components].fixed :=FALSE;
964     dM_dt.fixed :=TRUE;
965     M.fixed :=FALSE;
966     dU_dt.fixed :=TRUE;
967     U.fixed :=FALSE;
968     Vol.fixed :=TRUE;
969     vol_liq.fixed :=TRUE;
970     tauv.fixed :=FALSE;
971     taul.fixed :=FALSE;
972     IF dynamic THEN
973     dMi_dt[cd.other_components].fixed :=FALSE;
974     Mi[cd.other_components].fixed :=TRUE;
975     dM_dt.fixed :=FALSE;
976     M.fixed :=TRUE;
977     dU_dt.fixed :=FALSE;
978     U.fixed :=TRUE;
979     Qin.fixed :=TRUE;
980     IF equilibrated THEN
981     state.P.fixed :=FALSE;
982     ELSE
983     state.T.fixed :=FALSE;
984     END IF;
985     vol_liq.fixed :=FALSE;
986     tauv.fixed :=TRUE;
987     taul.fixed :=TRUE;
988     q.fixed :=FALSE;
989     ELSE
990     dMi_dt[cd.other_components] :=0 {mole/sec};
991     dM_dt :=0 {mole/sec};
992     dU_dt :=0 {J/sec};
993     END IF;
994     END seqmod;
995    
996     METHOD specify;
997     RUN feed.specify;
998     RUN vapin.specify;
999     RUN liqin.specify;
1000     RUN seqmod;
1001     END specify;
1002    
1003     METHOD reset_to_adiabatic;
1004     RUN seqmod;
1005     q.fixed := FALSE;
1006     Qin.fixed := TRUE;
1007     Qin := 0{W};
1008     END reset_to_adiabatic;
1009    
1010     METHOD set_ode;
1011     t.ode_type :=-1;
1012     FOR i IN cd.other_components DO
1013     dMi_dt[i].ode_type :=2;
1014     Mi[i].ode_type :=1;
1015     dMi_dt[i].ode_id :=ode_offset;
1016     Mi[i].ode_id :=ode_offset;
1017     ode_offset :=ode_offset+1;
1018     END FOR;
1019     dM_dt.ode_type :=2;
1020     M.ode_type :=1;
1021     dM_dt.ode_id :=ode_offset;
1022     M.ode_id :=ode_offset;
1023     ode_offset :=ode_offset+1;
1024     dU_dt.ode_type :=2;
1025     U.ode_type :=1;
1026     dU_dt.ode_id :=ode_offset;
1027     U.ode_id :=ode_offset;
1028     ode_offset :=ode_offset+1;
1029     END set_ode;
1030     METHOD set_obs;
1031     Vol.obs_id :=obs_offset;
1032     vol_liq.obs_id :=obs_offset+1;
1033     state.T.obs_id :=obs_offset+2;
1034     state.P.obs_id :=obs_offset+3;
1035     Qin.obs_id :=obs_offset+4;
1036     feed.flow.obs_id :=obs_offset+5;
1037     vapin.flow.obs_id :=obs_offset+6;
1038     liqin.flow.obs_id :=obs_offset+7;
1039     liqout.flow.obs_id :=obs_offset+8;
1040     vapout.flow.obs_id :=obs_offset+9;
1041     obs_offset :=obs_offset+10;
1042     END set_obs;
1043     END feed_tray;
1044    
1045     MODEL condenser(
1046     vapin WILL_BE stream;
1047     vap_distillate WILL_BE stream;
1048     liq_distillate WILL_BE stream;
1049     liqout WILL_BE stream;
1050     partial WILL_BE boolean;
1051     t WILL_BE time;
1052     dynamic WILL_BE boolean;
1053     ode_offset WILL_BE ode_counter;
1054     obs_offset WILL_BE obs_counter;
1055     ) WHERE (
1056     vapin, liqout WILL_NOT_BE_THE_SAME;
1057     vapin, vap_distillate, liq_distillate WILL_NOT_BE_THE_SAME;
1058     vapin.cd, liqout.cd, liq_distillate.cd,vap_distillate.cd WILL_BE_THE_SAME;
1059     vap_distillate.pd.phase_indicator == 'V';
1060     liq_distillate.pd.phase_indicator == 'L';
1061     liqout.pd.phase_indicator == 'L';
1062     vapin.pd.phase_indicator == 'V';
1063     ) REFINES flash_base;
1064     NOTES
1065     'purpose' SELF {
1066     This MODEL can be used as a partial or a total condenser and would
1067     normally be used in a column model.
1068     The user supplies all streams, a partial boolean, time, a dynamic
1069     boolean and obs and ode counters.
1070     The partial boolean is used to convert from a total condenser to a
1071     partial condenser. If partial is FALSE then vap_distillate is fixed
1072     and the user is expected to set the flow rate to zero so there is no
1073     vapor product. If partial is TRUE then liq_distillate is fixed
1074     and the user is expected to set the flow rate to zero so there is no
1075     liquid product. Both vapor and liquid products are possible both it
1076     is up to the user to define what fraction of the product will be vapor
1077     and what fraction liquid.
1078     If equilibrated is TRUE, V-L equilibrium will be
1079     attempted, OTHERWISE the unit will solve only the mass balances.
1080     }
1081     'developer-Duncan' SELF {
1082     This is a simple dynamic model of a condenser. The user creates a
1083     vapor feed and product, 2 liquid products, a partial
1084     boolean along with time, a dynamic boolean and ode and obs
1085     counters. We do the assembly of the condenser VLE MODEL from the given
1086     output stream states.
1087     }
1088     END NOTES;
1089     cd ALIASES vapin.cd;
1090     P ALIASES liq.P;
1091     T ALIASES liq.T;
1092     equilibrated ALIASES liq_distillate.equilibrated;
1093     (* condenser thermo options are derived from product streams *)
1094     pdL IS_A phases_data('L','none',liq_distillate.pd.liquid1_option,'none');
1095     pdVL IS_A phases_data('VL', vap_distillate.pd.vapor_option,
1096     liq.pd.liquid1_option, 'none');
1097     liq IS_A stream(cd, pdL, equilibrated);
1098    
1099     phaseVL[VLphases] ALIASES
1100     (vap_distillate.phase['vapor'],liq.phase['liquid1'])
1101     WHERE VLphases IS_A set OF symbol_constant
1102     WITH_VALUE ('vapor','liquid1');
1103     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
1104    
1105     out[outs] ALIASES (liqout, liq_distillate) WHERE outs
1106     IS_A set OF integer_constant;
1107     n_outs IS_A integer_constant;
1108     n_outs :== CARD[outs];
1109    
1110     split IS_A splitter(liq,n_outs,out);
1111    
1112     dMi_dt[cd.other_components] IS_A molar_rate;
1113     M,Mi[cd.components],Ml,Mv IS_A mole;
1114     dM_dt IS_A molar_rate;
1115     dU_dt IS_A energy_rate;
1116     U IS_A energy;
1117     Vol,vol_liq,vol_vap IS_A volume;
1118     Qin IS_A energy_rate;
1119     flowscale IS_A molar_rate_scale;
1120    
1121     (* component material balances *)
1122     FOR i IN cd.other_components CREATE
1123     dMi_dt[i]/flowscale=(vapin.f[i]-vap_distillate.f[i]-liq.f[i])/flowscale;
1124     END FOR;
1125     (* overall material balance *)
1126     dM_dt/flowscale=(vapin.flow-vap_distillate.flow-liq.flow)/flowscale;
1127    
1128     reflux_ratio IS_A factor;
1129     reflux_eqn: (liqout.flow - reflux_ratio * (vap_distillate.flow+
1130     liq_distillate.flow))/ flowscale = 0;
1131    
1132     FOR i IN cd.components CREATE
1133     Mi[i]=Ml*state.phase['liquid1'].y[i]+Mv*state.phase['vapor'].y[i];
1134     END FOR;
1135     Vol=vol_liq+vol_vap;
1136     vol_liq=Ml*state.phase['liquid1'].v_y;
1137     vol_vap=Mv*state.phase['vapor'].v_y;
1138     M=Ml+Mv;
1139     state.phase_fraction['vapor'] * M = Mv;
1140    
1141     (* overall energy balance *)
1142     H_flowscale IS_A energy_rate_scale;
1143    
1144     dU_dt/H_flowscale=(vapin.H_flow+Qin-vap_distillate.H_flow
1145     -liq.H_flow)/H_flowscale;
1146    
1147     U/H_flowscale = (state.phase['vapor'].h_y*Mv+state.phase['liquid1'].h_y*Ml)
1148     /H_flowscale;
1149    
1150     boundwidth IS_A bound_width;
1151     METHODS
1152     METHOD check_self;
1153     IF (liqout.flow < 1e-4 {mole/s}) THEN
1154     STOP {No reflux/liquid flow in condenser};
1155     END IF;
1156     IF (vapin.flow < 1e-4 {mole/s}) THEN
1157     STOP {No vapor feed to condenser};
1158     END IF;
1159     IF partial THEN
1160     IF (vap_distillate.flow < 1e-4 {mole/s}) THEN
1161     STOP {No liquid distillate product from Condenser};
1162     END IF;
1163     ELSE
1164     IF (liq_distillate.flow < 1e-4 {mole/s}) THEN
1165     STOP {No vapor distillate product from Condenser};
1166     END IF;
1167     END IF;
1168     IF (abs(vapin.flow - vap_distillate.flow- liq_distillate.flow
1169     - liqout.flow) > 1.0e-4) THEN
1170     STOP {Condenser violates overall mass-balance};
1171     END IF;
1172     RUN state.check_self;
1173     END check_self;
1174    
1175     METHOD check_all;
1176     RUN vapin.check_self;
1177     IF partial THEN
1178     RUN vap_distillate.check_self;
1179     ELSE
1180     RUN liq_distillate.check_self;
1181     END IF;
1182     RUN liqout.check_self;
1183     RUN check_self;
1184     END check_all;
1185    
1186     METHOD default_self;
1187     boundwidth :=10;
1188     flowscale := vapin.Details.flowscale;
1189     H_flowscale := vapin.Details.H_flowscale;
1190     dMi_dt[cd.other_components] :=0 {mole/sec};
1191     dMi_dt[cd.other_components].lower_bound :=-1e100 {mole/sec};
1192     dM_dt :=0 {mole/sec};
1193     dM_dt.lower_bound :=-1e100 {mole/sec};
1194     dU_dt :=0 {J/sec};
1195     dynamic :=FALSE;
1196     partial :=FALSE;
1197     t :=0 {s};
1198     RUN liq.default_self;
1199     RUN split.default_self;
1200     RUN state.default_self;
1201     END default_self;
1202    
1203     METHOD default_all;
1204     Qin := 0 {watt};
1205     RUN vapin.default_self;
1206     RUN vap_distillate.default_self;
1207     RUN liq_distillate.default_self;
1208     RUN liqout.default_self;
1209     RUN default_self;
1210     END default_all;
1211    
1212     METHOD bound_self;
1213     state.boundwidth := boundwidth;
1214     RUN liq.bound_self;
1215     RUN split.bound_self;
1216     RUN state.bound_self;
1217     END bound_self;
1218    
1219     METHOD bound_all;
1220     vapin.boundwidth := boundwidth;
1221     distillate.boundwidth := boundwidth;
1222     liqout.boundwidth := boundwidth;
1223     RUN vapin.bound_self;
1224     RUN vap_distillate.bound_self;
1225     RUN liq_distillate.bound_self;
1226     RUN liqout.bound_self;
1227     RUN bound_self;
1228     END bound_all;
1229    
1230     METHOD scale_self;
1231     flowscale := vapin.flow;
1232     H_flowscale := vapin.H_flow;
1233     RUN liq.scale_self;
1234     RUN split.scale_self;
1235     RUN state.scale_self;
1236     END scale_self;
1237    
1238     METHOD scale_all;
1239     RUN vapin.scale_self;
1240     RUN vap_distillate.scale_self;
1241     RUN liq_distillate.scale_self;
1242     RUN liqout.scale_self;
1243     RUN scale_self;
1244     END scale_all;
1245    
1246     METHOD seqmod;
1247     RUN state.specify;
1248     state.y[cd.components].fixed := FALSE;
1249     state.phase_fraction['vapor'].fixed :=FALSE;
1250     IF equilibrated THEN
1251     state.T.fixed :=FALSE;
1252     ELSE
1253     state.T.fixed :=TRUE;
1254     END IF;
1255     RUN split.seqmod;
1256     split.split[1].fixed :=FALSE;
1257     liqout.flow.fixed :=FALSE;
1258     vap_distillate.flow.fixed :=FALSE;
1259     liq_distillate.flow.fixed :=FALSE;
1260     IF partial THEN
1261     liq_distillate.flow.fixed :=TRUE;
1262     ELSE
1263     vap_distillate.flow.fixed :=TRUE;
1264     END IF;
1265     reflux_ratio.fixed :=TRUE;
1266     dMi_dt[cd.other_components].fixed :=TRUE;
1267     Mi[cd.other_components].fixed :=FALSE;
1268     dM_dt.fixed :=TRUE;
1269     M.fixed :=FALSE;
1270     dU_dt.fixed :=TRUE;
1271     U.fixed :=FALSE;
1272     Qin.fixed :=FALSE;
1273     Vol.fixed :=TRUE;
1274     vol_liq.fixed :=TRUE;
1275     IF dynamic THEN
1276     dMi_dt[cd.other_components].fixed :=FALSE;
1277     Mi[cd.other_components].fixed :=TRUE;
1278     dM_dt.fixed :=FALSE;
1279     M.fixed :=TRUE;
1280     dU_dt.fixed :=FALSE;
1281     U.fixed :=TRUE;
1282     Qin.fixed :=TRUE;
1283     IF equilibrated THEN
1284     state.P.fixed :=FALSE;
1285     ELSE
1286     state.T.fixed :=FALSE;
1287     END IF;
1288     vol_liq.fixed :=FALSE;
1289     reflux_ratio.fixed :=FALSE;
1290     state.phase_fraction['vapor'].fixed :=FALSE;
1291     liqout.flow.fixed :=TRUE;
1292     (* liqout.Details.state.slack_PhaseDisappearance['liquid1'].fixed :=TRUE;*)
1293     vap_distillate.flow.fixed :=TRUE;
1294     liq_distillate.flow.fixed :=TRUE;
1295     ELSE
1296     dMi_dt[cd.other_components] :=0 {mole/sec};
1297     dM_dt :=0 {mole/sec};
1298     dU_dt :=0 {J/sec};
1299     END IF;
1300     END seqmod;
1301    
1302     METHOD specify;
1303     RUN vapin.specify;
1304     RUN seqmod;
1305     END specify;
1306    
1307     METHOD set_ode;
1308     t.ode_type :=-1;
1309     FOR i IN cd.other_components DO
1310     dMi_dt[i].ode_type :=2;
1311     Mi[i].ode_type :=1;
1312     dMi_dt[i].ode_id :=ode_offset;
1313     Mi[i].ode_id :=ode_offset;
1314     ode_offset :=ode_offset+1;
1315     END FOR;
1316     dM_dt.ode_type :=2;
1317     M.ode_type :=1;
1318     dM_dt.ode_id :=ode_offset;
1319     M.ode_id :=ode_offset;
1320     ode_offset :=ode_offset+1;
1321     dU_dt.ode_type :=2;
1322     U.ode_type :=1;
1323     dU_dt.ode_id :=ode_offset;
1324     U.ode_id :=ode_offset;
1325     ode_offset :=ode_offset+1;
1326     END set_ode;
1327    
1328     METHOD set_obs;
1329     Vol.obs_id :=obs_offset;
1330     vol_liq.obs_id :=obs_offset+1;
1331     state.T.obs_id :=obs_offset+2;
1332     state.P.obs_id :=obs_offset+3;
1333     Qin.obs_id :=obs_offset+4;
1334     vapin.flow.obs_id :=obs_offset+5;
1335     liqout.flow.obs_id :=obs_offset+6;
1336     vap_distillate.flow.obs_id :=obs_offset+7;
1337     liq_distillate.flow.obs_id :=obs_offset+8;
1338     obs_offset :=obs_offset+9;
1339     END set_obs;
1340     END condenser;
1341    
1342     MODEL reboiler(
1343     liqin WILL_BE stream;
1344     vap_bottom WILL_BE stream;
1345     liq_bottom WILL_BE stream;
1346     vapout WILL_BE stream;
1347     partial WILL_BE boolean;
1348     t WILL_BE time;
1349     dynamic WILL_BE boolean;
1350     ode_offset WILL_BE ode_counter;
1351     obs_offset WILL_BE obs_counter;
1352     ) WHERE (
1353     liqin, vapout WILL_NOT_BE_THE_SAME;
1354     liqin, vap_bottom, liq_bottom WILL_NOT_BE_THE_SAME;
1355     liqin.cd, vapout.cd, liq_bottom.cd,vap_bottom.cd WILL_BE_THE_SAME;
1356     vap_bottom.pd.phase_indicator == 'V';
1357     liq_bottom.pd.phase_indicator == 'L';
1358     vapout.pd.phase_indicator == 'V';
1359     liqin.pd.phase_indicator == 'L';
1360     ) REFINES flash_base;
1361     NOTES
1362     'purpose' SELF {
1363     This MODEL can be used as a partial or a total reboiler and would
1364     normally be used in a column model.
1365     The user supplies all streams, a partial boolean, time, a dynamic
1366     boolean and obs and ode counters.
1367     The partial boolean is used to convert from a total reboiler to a
1368     partial reboiler. If partial is FALSE then liq_bottoms is fixed
1369     and the user is expected to set the flow rate to zero so there is no
1370     liquid product. If partial is TRUE then vap_bottoms is fixed
1371     and the user is expected to set the flow rate to zero so there is no
1372     vapor product. Both vapor and liquid products are possible both it
1373     is up to the user to define what fraction of the product will be vapor
1374     and what fraction liquid.
1375     If equilibrated is TRUE, V-L equilibrium will be
1376     attempted, OTHERWISE the unit will solve only the mass balances.
1377     }
1378     'developer-Duncan' SELF {
1379     This is a simple dynamic model of a reboiler. The user creates a
1380     vapor product, a liquid feed and products, a partial
1381     boolean along with time, a dynamic boolean and ode and obs
1382     counters. We do the assembly of the condenser VLE MODEL from the given
1383     output stream states.
1384     }
1385     END NOTES;
1386     cd ALIASES liqin.cd;
1387     P ALIASES liq_bottom.P;
1388     T ALIASES liq_bottom.T;
1389     equilibrated ALIASES liq_bottom.equilibrated;
1390     (* reboiler thermo options are derived from product streams *)
1391     pdV IS_A phases_data('V', vapout.pd.vapor_option,'none','none');
1392     vap IS_A stream(cd,pdV,equilibrated);
1393     pdVL IS_A phases_data('VL', vap.pd.vapor_option,
1394     liq_bottom.pd.liquid1_option, 'none');
1395     phaseVL[VLphases] ALIASES
1396     (vap.phase['vapor'],liq_bottom.phase['liquid1'])
1397     WHERE VLphases IS_A set OF symbol_constant
1398     WITH_VALUE ('vapor','liquid1');
1399     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
1400    
1401     out[outs] ALIASES (vapout,vap_bottom)
1402     WHERE outs IS_A set OF integer_constant;
1403     n_outs IS_A integer_constant;
1404     n_outs :==CARD[outs];
1405    
1406     split IS_A splitter(vap,n_outs,out);
1407    
1408    
1409     dMi_dt[cd.other_components] IS_A molar_rate;
1410     M,Mi[cd.components],Ml,Mv IS_A mole;
1411     dM_dt IS_A molar_rate;
1412     dU_dt IS_A energy_rate;
1413     U IS_A energy;
1414     Vol,vol_liq,vol_vap IS_A volume;
1415     Qin IS_A energy_rate;
1416     flowscale IS_A molar_rate_scale;
1417    
1418     (* component material balances *)
1419     FOR i IN cd.other_components CREATE
1420     dMi_dt[i]/flowscale=(liqin.f[i]-vap.f[i]-liq_bottom.f[i])/flowscale;
1421     END FOR;
1422     (* overall material balance *)
1423     dM_dt/flowscale=(liqin.flow-vap.flow-liq_bottom.flow)/flowscale;
1424    
1425     reboil_ratio IS_A factor;
1426     reboil_eqn: (vapout.flow - reboil_ratio * (vap_bottom.flow+
1427     liq_bottom.flow))/ flowscale = 0;
1428    
1429     FOR i IN cd.components CREATE
1430     Mi[i]=Ml*state.phase['liquid1'].y[i]+Mv*state.phase['vapor'].y[i];
1431     END FOR;
1432     Vol=vol_liq+vol_vap;
1433     vol_liq=Ml*state.phase['liquid1'].v_y;
1434     vol_vap=Mv*state.phase['vapor'].v_y;
1435     M=Ml+Mv;
1436     state.phase_fraction['vapor'] * M = Mv;
1437    
1438     (* overall energy balance *)
1439     H_flowscale IS_A energy_rate_scale;
1440    
1441     dU_dt/H_flowscale=(liqin.H_flow+Qin-vap.H_flow
1442     -liq_bottom.H_flow)/H_flowscale;
1443    
1444     U/H_flowscale = (state.phase['vapor'].h_y*Mv+state.phase['liquid1'].h_y*Ml)
1445     /H_flowscale;
1446    
1447     boundwidth IS_A bound_width;
1448     METHODS
1449     METHOD check_self;
1450     IF (vapout.flow < 1e-4 {mole/s}) THEN
1451     STOP {No reboil/vapor flow out of reboiler};
1452     END IF;
1453     IF (liqin.flow < 1e-4 {mole/s}) THEN
1454     STOP {No liquid feed to reboiler};
1455     END IF;
1456     IF partial THEN
1457     IF (liq_bottom.flow < 1e-4 {mole/s}) THEN
1458     STOP {No liquid bottom product from reboiler};
1459     END IF;
1460     ELSE
1461     IF (vap_bottom.flow < 1e-4 {mole/s}) THEN
1462     STOP {No vapor bottom product from reboiler};
1463     END IF;
1464     END IF;
1465     IF (abs(liqin.flow - vap_bottom.flow- liq_bottom.flow
1466     - vapout.flow) > 1.0e-4) THEN
1467     STOP {Reboiler violates overall mass-balance};
1468     END IF;
1469     RUN state.check_self;
1470     END check_self;
1471    
1472     METHOD check_all;
1473     RUN liqin.check_self;
1474     IF partial THEN
1475     RUN liq_bottom.check_self;
1476     ELSE
1477     RUN vap_bottom.check_self;
1478     END IF;
1479     RUN vapout.check_self;
1480     RUN check_self;
1481     END check_all;
1482    
1483     METHOD default_self;
1484     boundwidth :=10;
1485     flowscale := liqin.Details.flowscale;
1486     H_flowscale := liqin.Details.H_flowscale;
1487     dMi_dt[cd.other_components] :=0 {mole/sec};
1488     dMi_dt[cd.other_components].lower_bound :=-1e100 {mole/sec};
1489     dM_dt :=0 {mole/sec};
1490     dM_dt.lower_bound :=-1e100 {mole/sec};
1491     dU_dt :=0 {J/sec};
1492     dynamic :=FALSE;
1493     partial :=TRUE;
1494     t :=0 {s};
1495     RUN vap.default_self;
1496     RUN split.default_self;
1497     RUN state.default_self;
1498     END default_self;
1499    
1500     METHOD default_all;
1501     Qin := 0 {watt};
1502     RUN liqin.default_self;
1503     RUN vap_bottom.default_self;
1504     RUN liq_bottom.default_self;
1505     RUN vapout.default_self;
1506     RUN default_self;
1507     END default_all;
1508    
1509     METHOD bound_self;
1510     state.boundwidth := boundwidth;
1511     RUN vap.bound_self;
1512     RUN splitbound_self;
1513     RUN state.bound_self;
1514     END bound_self;
1515    
1516     METHOD bound_all;
1517     liqin.boundwidth := boundwidth;
1518     distillate.boundwidth := boundwidth;
1519     vapout.boundwidth := boundwidth;
1520     RUN liqin.bound_self;
1521     RUN vap_bottom.bound_self;
1522     RUN liq_bottom.bound_self;
1523     RUN vapout.bound_self;
1524     RUN bound_self;
1525     END bound_all;
1526    
1527     METHOD scale_self;
1528     flowscale := liqin.flow;
1529     H_flowscale := liqin.H_flow;
1530     RUN vap.scale_self;
1531     RUN split.scale_self;
1532     RUN state.scale_self;
1533     END scale_self;
1534    
1535     METHOD scale_all;
1536     RUN liqin.scale_self;
1537     RUN vap_bottom.scale_self;
1538     RUN liq_bottom.scale_self;
1539     RUN vapout.scale_self;
1540     RUN scale_self;
1541     END scale_all;
1542    
1543     METHOD seqmod;
1544     RUN state.specify;
1545     state.y[cd.components].fixed := FALSE;
1546     state.phase_fraction['vapor'].fixed :=FALSE;
1547     IF equilibrated THEN
1548     state.T.fixed :=FALSE;
1549     ELSE
1550     state.T.fixed :=TRUE;
1551     END IF;
1552     RUN split.seqmod;
1553     split.split[1].fixed :=FALSE;
1554     vapout.flow.fixed :=FALSE;
1555     vap_bottom.flow.fixed :=FALSE;
1556     liq_bottom.flow.fixed :=FALSE;
1557     IF partial THEN
1558     vap_bottom.flow.fixed :=TRUE;
1559     ELSE
1560     liq_bottom.flow.fixed :=TRUE;
1561     END IF;
1562     reboil_ratio.fixed :=TRUE;
1563     dMi_dt[cd.other_components].fixed :=TRUE;
1564     Mi[cd.other_components].fixed :=FALSE;
1565     dM_dt.fixed :=TRUE;
1566     M.fixed :=FALSE;
1567     dU_dt.fixed :=TRUE;
1568     U.fixed :=FALSE;
1569     Qin.fixed :=FALSE;
1570     Vol.fixed :=TRUE;
1571     vol_liq.fixed :=TRUE;
1572     IF dynamic THEN
1573     dMi_dt[cd.other_components].fixed :=FALSE;
1574     Mi[cd.other_components].fixed :=TRUE;
1575     dM_dt.fixed :=FALSE;
1576     M.fixed :=TRUE;
1577     dU_dt.fixed :=FALSE;
1578     U.fixed :=TRUE;
1579     Qin.fixed :=TRUE;
1580     IF equilibrated THEN
1581     state.P.fixed :=FALSE;
1582     ELSE
1583     state.T.fixed :=FALSE;
1584     END IF;
1585     vol_liq.fixed :=FALSE;
1586     reboil_ratio.fixed :=FALSE;
1587     state.phase_fraction['vapor'].fixed :=FALSE;
1588     vapout.flow.fixed :=TRUE;
1589     vap_bottom.flow.fixed :=TRUE;
1590     liq_bottom.flow.fixed :=TRUE;
1591     ELSE
1592     dMi_dt[cd.other_components] :=0 {mole/sec};
1593     dM_dt :=0 {mole/sec};
1594     dU_dt :=0 {J/sec};
1595     END IF;
1596     END seqmod;
1597    
1598     METHOD specify;
1599     RUN liqin.specify;
1600     RUN seqmod;
1601     END specify;
1602    
1603     METHOD set_ode;
1604     t.ode_type :=-1;
1605     FOR i IN cd.other_components DO
1606     dMi_dt[i].ode_type :=2;
1607     Mi[i].ode_type :=1;
1608     dMi_dt[i].ode_id :=ode_offset;
1609     Mi[i].ode_id :=ode_offset;
1610     ode_offset :=ode_offset+1;
1611     END FOR;
1612     dM_dt.ode_type :=2;
1613     M.ode_type :=1;
1614     dM_dt.ode_id :=ode_offset;
1615     M.ode_id :=ode_offset;
1616     ode_offset :=ode_offset+1;
1617     dU_dt.ode_type :=2;
1618     U.ode_type :=1;
1619     dU_dt.ode_id :=ode_offset;
1620     U.ode_id :=ode_offset;
1621     ode_offset :=ode_offset+1;
1622     END set_ode;
1623    
1624     METHOD set_obs;
1625     Vol.obs_id :=obs_offset;
1626     vol_liq.obs_id :=obs_offset+1;
1627     state.T.obs_id :=obs_offset+2;
1628     state.P.obs_id :=obs_offset+3;
1629     Qin.obs_id :=obs_offset+4;
1630     liqin.flow.obs_id :=obs_offset+5;
1631     vapout.flow.obs_id :=obs_offset+6;
1632     vap_bottom.flow.obs_id :=obs_offset+7;
1633     liq_bottom.flow.obs_id :=obs_offset+8;
1634     obs_offset :=obs_offset+9;
1635     END set_obs;
1636     END reboiler;
1637    
1638     (**************************************************************************)
1639     (**************************************************************************)
1640    
1641    
1642     MODEL testflashmodel() REFINES testcmumodel;
1643     (* root fo flash based test models *)
1644     END testflashmodel;
1645    
1646     MODEL test_vapor_liquid_flash() REFINES testflashmodel();
1647    
1648     (* the next 5 are probably used throughout a flowsheet *)
1649     cd IS_A components_data(['methanol','ethanol','water'],'water');
1650     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1651     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1652     pdVL IS_A phases_data('VL', 'Pitzer_vapor_mixture',
1653     'UNIFAC_liquid_mixture', 'none');
1654     equilibrated IS_A boolean;
1655     feed IS_A stream(cd, pdVL, equilibrated);
1656     liq IS_A stream(cd, pdL, equilibrated);
1657     vap IS_A stream(cd, pdV, equilibrated);
1658     t IS_A time;
1659     dynamic IS_A boolean;
1660     ode_offset IS_A ode_counter;
1661     obs_offset IS_A obs_counter;
1662     fl1 IS_A vapor_liquid_flash(feed, vap, liq,t,dynamic,ode_offset,obs_offset);
1663    
1664     (* boundwidth might be unit specific *)
1665     boundwidth IS_A bound_width;
1666    
1667     METHODS
1668    
1669     METHOD default_all;
1670     RUN default_self;
1671     END default_all;
1672    
1673     METHOD default_self;
1674     boundwidth := 10;
1675     equilibrated :=TRUE;
1676     ode_offset :=1;
1677     obs_offset :=1;
1678     RUN feed.default_self;
1679     RUN liq.default_self;
1680     RUN vap.default_self;
1681     RUN fl1.default_self;
1682     (* or could be RUN fl1.default_all; *)
1683     END default_self;
1684    
1685     METHOD check_all;
1686     RUN check_self;
1687     END check_all;
1688    
1689     METHOD check_self;
1690     RUN feed.check_self;
1691     RUN liq.check_self;
1692     RUN vap.check_self;
1693     RUN fl1.check_self;
1694     (* or could be RUN check_all; *)
1695     END check_self;
1696    
1697     METHOD bound_all;
1698     RUN bound_self;
1699     END bound_all;
1700    
1701     METHOD bound_self;
1702     fl1.boundwidth := boundwidth;
1703     liq.boundwidth := boundwidth;
1704     vap.boundwidth := boundwidth;
1705     feed.boundwidth := boundwidth;
1706     (* The right, later reusable, way to finish this method is as follows:
1707     RUN feed.bound_self;
1708     RUN liq.bound_self;
1709     RUN vap.bound_self;
1710     RUN fl1.bound_self;
1711     * where we didn't have to look inside the parts we're using because
1712     * we know they follow the standard in system.a4l.
1713     *)
1714     (* The quick and dirty way, since there are no parts passed into
1715     * this MODEL is like so:
1716     *)
1717     RUN fl1.bound_all;
1718     (* This works, but we had to look into the VLflash MODEL to be sure. *)
1719     END bound_self;
1720    
1721     METHOD scale_self;
1722     RUN feed.scale_self;
1723     RUN liq.scale_self;
1724     RUN vap.scale_self;
1725     RUN fl1.scale_self;
1726     (* or could be RUN fl1.scale_all; *)
1727     END scale_self;
1728    
1729     METHOD specify;
1730     RUN fl1.specify;
1731     END specify;
1732    
1733     METHOD values;
1734     feed.P := 1 {atm};
1735     feed.T := 365 {K};
1736     feed.f['methanol'] := 0.01 {kmol/s};
1737     feed.f['ethanol'] := 0.015 {kmol/s};
1738     feed.f['water'] := 0.02 {kmol/s};
1739     fl1.state.phase_fraction['vapor'] := 0.5;
1740     fl1.P := 1 {atm};
1741     fl1.T := 365 {K};
1742     fl1.Qin := 0 {kW};
1743     fl1.Vol := 10 {m^3};
1744     fl1.vol_liq := 3 {m^3};
1745     END values;
1746     END test_vapor_liquid_flash;
1747    
1748    
1749     MODEL test_tray() REFINES testflashmodel();
1750    
1751     (* the next 5 are probably used throughout a flowsheet *)
1752     cd IS_A components_data(['methanol','ethanol','water'],'water');
1753     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1754     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1755    
1756     equilibrated IS_A boolean;
1757     vin IS_A stream(cd, pdV, equilibrated);
1758     lin IS_A stream(cd, pdL, equilibrated);
1759     lout IS_A stream(cd, pdL, equilibrated);
1760     vout IS_A stream(cd, pdV, equilibrated);
1761     t IS_A time;
1762     dynamic IS_A boolean;
1763     ode_offset IS_A ode_counter;
1764     obs_offset IS_A obs_counter;
1765     fl1 IS_A tray(lin,vin,lout,vout,t,dynamic,ode_offset,obs_offset);
1766    
1767     (* boundwidth might be unit specific *)
1768     boundwidth IS_A bound_width;
1769    
1770     METHODS
1771    
1772     METHOD default_all;
1773     RUN default_self;
1774     END default_all;
1775    
1776     METHOD default_self;
1777     boundwidth := 10;
1778     equilibrated :=TRUE;
1779     ode_offset :=1;
1780     obs_offset :=1;
1781     RUN vin.default_self;
1782     RUN lin.default_self;
1783     RUN lout.default_self;
1784     RUN vout.default_self;
1785     RUN fl1.default_self;
1786     (* or could be RUN fl1.default_all; *)
1787     END default_self;
1788    
1789     METHOD check_all;
1790     RUN check_self;
1791     END check_all;
1792    
1793     METHOD check_self;
1794     RUN vin.check_self;
1795     RUN lin.check_self;
1796     RUN lout.check_self;
1797     RUN vout.check_self;
1798     RUN fl1.check_self;
1799     (* or could be RUN check_all; *)
1800     END check_self;
1801    
1802     METHOD bound_all;
1803     RUN bound_self;
1804     END bound_all;
1805    
1806     METHOD bound_self;
1807     fl1.boundwidth := boundwidth;
1808     lin.boundwidth := boundwidth;
1809     vin.boundwidth := boundwidth;
1810     lout.boundwidth := boundwidth;
1811     vout.boundwidth := boundwidth;
1812     (* The right, later reusable, way to finish this method is as follows:
1813     RUN vin.bound_self
1814     RUN lin.bound_self;
1815     RUN lout.bound_self;
1816     RUN vout.bound_self;
1817     RUN fl1.bound_self;
1818     * where we didn't have to look inside the parts we're using because
1819     * we know they follow the standard in system.a4l.
1820     *)
1821     (* The quick and dirty way, since there are no parts passed into
1822     * this MODEL is like so:
1823     *)
1824     RUN fl1.bound_all;
1825     (* This works, but we had to look into the VLflash MODEL to be sure. *)
1826     END bound_self;
1827    
1828     METHOD scale_self;
1829     RUN vin.scale_self;
1830     RUN lin.scale_self;
1831     RUN lout.scale_self;
1832     RUN vout.scale_self;
1833     RUN fl1.scale_self;
1834     (* or could be RUN fl1.scale_all; *)
1835     END scale_self;
1836    
1837     METHOD specify;
1838     RUN fl1.specify;
1839     END specify;
1840    
1841     METHOD values;
1842     vin.P := 1 {atm};
1843     vin.T := 365 {K};
1844     vin.f['methanol'] := 0.01 {kmol/s};
1845     vin.f['ethanol'] := 0.015 {kmol/s};
1846     vin.f['water'] := 0.02 {kmol/s};
1847     lin.P := 1 {atm};
1848     lin.T := 365 {K};
1849     lin.f['methanol'] := 0.01 {kmol/s};
1850     lin.f['ethanol'] := 0.015 {kmol/s};
1851     lin.f['water'] := 0.02 {kmol/s};
1852     fl1.cmo_ratio := 1;
1853     fl1.P := 1 {atm};
1854     fl1.T := 365 {K};
1855     fl1.Qin := 0 {kW};
1856     fl1.Vol := 10 {m^3};
1857     fl1.vol_liq := 3 {m^3};
1858     END values;
1859    
1860     END test_tray;
1861    
1862    
1863     MODEL test_feed_tray() REFINES testflashmodel();
1864    
1865     (* the next 5 are probably used throughout a flowsheet *)
1866     cd IS_A components_data(['methanol','ethanol','water'],'water');
1867     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1868     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1869    
1870     equilibrated IS_A boolean;
1871     feed IS_A stream(cd, pdV, equilibrated);
1872     vin IS_A stream(cd, pdV, equilibrated);
1873     lin IS_A stream(cd, pdL, equilibrated);
1874     lout IS_A stream(cd, pdL, equilibrated);
1875     vout IS_A stream(cd, pdV, equilibrated);
1876     t IS_A time;
1877     dynamic IS_A boolean;
1878     ode_offset IS_A ode_counter;
1879     obs_offset IS_A obs_counter;
1880     fl1 IS_A feed_tray(feed,lin,vin,lout,vout,t,dynamic,ode_offset,obs_offset);
1881    
1882     (* boundwidth might be unit specific *)
1883     boundwidth IS_A bound_width;
1884    
1885     METHODS
1886    
1887     METHOD default_all;
1888     RUN default_self;
1889     END default_all;
1890    
1891     METHOD default_self;
1892     boundwidth := 10;
1893     equilibrated :=TRUE;
1894     ode_offset :=1;
1895     obs_offset :=1;
1896     RUN feed.default_self;
1897     RUN vin.default_self;
1898     RUN lin.default_self;
1899     RUN lout.default_self;
1900     RUN vout.default_self;
1901     RUN fl1.default_self;
1902     END default_self;
1903    
1904     METHOD check_all;
1905     RUN check_self;
1906     END check_all;
1907    
1908     METHOD check_self;
1909     RUN feed.check_self;
1910     RUN vin.check_self;
1911     RUN lin.check_self;
1912     RUN lout.check_self;
1913     RUN vout.check_self;
1914     RUN fl1.check_self;
1915     END check_self;
1916    
1917     METHOD bound_all;
1918     RUN bound_self;
1919     END bound_all;
1920    
1921     METHOD bound_self;
1922     fl1.boundwidth := boundwidth;
1923     feed.boundwidth := boundwidth;
1924     lin.boundwidth := boundwidth;
1925     vin.boundwidth := boundwidth;
1926     lout.boundwidth := boundwidth;
1927     vout.boundwidth := boundwidth;
1928     RUN fl1.bound_all;
1929     END bound_self;
1930    
1931     METHOD scale_self;
1932     RUN feed.scale_self;
1933     RUN vin.scale_self;
1934     RUN lin.scale_self;
1935     RUN lout.scale_self;
1936     RUN vout.scale_self;
1937     RUN fl1.scale_self;
1938     END scale_self;
1939    
1940     METHOD specify;
1941     RUN fl1.specify;
1942     END specify;
1943    
1944     METHOD values;
1945     feed.P := 1 {atm};
1946     feed.T := 365 {K};
1947     feed.f['methanol'] := 0.01 {kmol/s};
1948     feed.f['ethanol'] := 0.015 {kmol/s};
1949     feed.f['water'] := 0.02 {kmol/s};
1950     vin.P := 1 {atm};
1951     vin.T := 365 {K};
1952     vin.f['methanol'] := 0.01 {kmol/s};
1953     vin.f['ethanol'] := 0.015 {kmol/s};
1954     vin.f['water'] := 0.02 {kmol/s};
1955     lin.P := 1 {atm};
1956     lin.T := 365 {K};
1957     lin.f['methanol'] := 0.01 {kmol/s};
1958     lin.f['ethanol'] := 0.015 {kmol/s};
1959     lin.f['water'] := 0.02 {kmol/s};
1960     fl1.q := 0;
1961     fl1.P := 1 {atm};
1962     fl1.T := 365 {K};
1963     fl1.Qin := 0 {kW};
1964     fl1.Vol := 10 {m^3};
1965     fl1.vol_liq := 3 {m^3};
1966     END values;
1967     END test_feed_tray;
1968    
1969    
1970    
1971     MODEL test_condenser() REFINES testflashmodel();
1972    
1973     (* the next 5 are probably used throughout a flowsheet *)
1974     cd IS_A components_data(['methanol','ethanol','water'],'water');
1975     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1976     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1977     partial IS_A boolean;
1978     equilibrated IS_A boolean;
1979     vapin IS_A stream(cd, pdV, equilibrated);
1980     liq IS_A stream(cd, pdL, equilibrated);
1981     liq_dist IS_A stream(cd, pdL, equilibrated);
1982     vap_dist IS_A stream(cd, pdV, equilibrated);
1983     t IS_A time;
1984     dynamic IS_A boolean;
1985     ode_offset IS_A ode_counter;
1986     obs_offset IS_A obs_counter;
1987     fl1 IS_A condenser(vapin,vap_dist,liq_dist,liq,partial,t,dynamic,
1988     ode_offset,obs_offset);
1989    
1990     (* boundwidth might be unit specific *)
1991     boundwidth IS_A bound_width;
1992    
1993     METHODS
1994    
1995     METHOD default_all;
1996     RUN default_self;
1997     END default_all;
1998    
1999     METHOD default_self;
2000     boundwidth := 10;
2001     equilibrated :=TRUE;
2002     ode_offset :=1;
2003     obs_offset :=1;
2004     RUN vapin.default_self;
2005     RUN liq.default_self;
2006     RUN vap_dist.default_self;
2007     RUN liq_dist.default_self;
2008     RUN fl1.default_self;
2009     (* or could be RUN fl1.default_all; *)
2010     END default_self;
2011    
2012     METHOD check_all;
2013     RUN check_self;
2014     END check_all;
2015    
2016     METHOD check_self;
2017     RUN vapin.check_self;
2018     RUN liq.check_self;
2019     IF partial THEN
2020     RUN vap_dist.check_self;
2021     ELSE
2022     RUN liq_dist.check_self;
2023     END IF;
2024     RUN fl1.check_self;
2025     (* or could be RUN fl1.check_all; *)
2026     END check_self;
2027    
2028     METHOD bound_all;
2029     RUN bound_self;
2030     END bound_all;
2031    
2032     METHOD bound_self;
2033     fl1.boundwidth := boundwidth;
2034     liq.boundwidth := boundwidth;
2035     liq_dist.boundwidth := boundwidth;
2036     vap_dist.boundwidth := boundwidth;
2037     vapin.boundwidth := boundwidth;
2038     RUN fl1.bound_all;
2039     END bound_self;
2040    
2041     METHOD scale_self;
2042     RUN vapin.scale_self;
2043     RUN liq.scale_self;
2044     RUN vap_dist.scale_self;
2045     RUN liq_dist.scale_self;
2046     RUN fl1.scale_self;
2047     END scale_self;
2048    
2049     METHOD specify;
2050     RUN fl1.specify;
2051     END specify;
2052    
2053     METHOD values;
2054     vapin.P := 1 {atm};
2055     vapin.T := 365 {K};
2056     vapin.f['methanol'] := 0.01 {kmol/s};
2057     vapin.f['ethanol'] := 0.015 {kmol/s};
2058     vapin.f['water'] := 0.02 {kmol/s};
2059     fl1.reflux_ratio :=1;
2060     fl1.P := 1 {atm};
2061     fl1.T := 365 {K};
2062     fl1.Qin := 0 {kW};
2063     fl1.Vol := 3 {m^3};
2064     fl1.vol_liq := 1 {m^3};
2065     END values;
2066     END test_condenser;
2067    
2068     MODEL test_reboiler() REFINES testflashmodel();
2069    
2070     (* the next 5 are probably used throughout a flowsheet *)
2071     cd IS_A components_data(['methanol','ethanol','water'],'water');
2072     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
2073     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
2074     partial IS_A boolean;
2075     equilibrated IS_A boolean;
2076     liqin IS_A stream(cd, pdL, equilibrated);
2077     vap IS_A stream(cd, pdV, equilibrated);
2078     liq_bot IS_A stream(cd, pdL, equilibrated);
2079     vap_bot IS_A stream(cd, pdV, equilibrated);
2080     t IS_A time;
2081     dynamic IS_A boolean;
2082     ode_offset IS_A ode_counter;
2083     obs_offset IS_A obs_counter;
2084     fl1 IS_A reboiler(liqin,vap_bot,liq_bot,vap,partial,t,dynamic,
2085     ode_offset,obs_offset);
2086    
2087     (* boundwidth might be unit specific *)
2088     boundwidth IS_A bound_width;
2089    
2090     METHODS
2091    
2092     METHOD default_all;
2093     RUN default_self;
2094     END default_all;
2095    
2096     METHOD default_self;
2097     boundwidth := 10;
2098     equilibrated :=TRUE;
2099     partial :=FALSE;
2100     ode_offset :=1;
2101     obs_offset :=1;
2102     RUN liqin.default_self;
2103     RUN vap.default_self;
2104     RUN vap_bot.default_self;
2105     RUN liq_bot.default_self;
2106     RUN fl1.default_self;
2107     (* or could be RUN fl1.default_all; *)
2108     END default_self;
2109    
2110     METHOD check_all;
2111     RUN check_self;
2112     END check_all;
2113    
2114     METHOD check_self;
2115     RUN liqin.check_self;
2116     RUN vap.check_self;
2117     IF partial THEN
2118     RUN liq_bot.check_self;
2119     ELSE
2120     RUN vap_bot.check_self;
2121     END IF;
2122     RUN fl1.check_self;
2123     (* or could be RUN check_all; *)
2124     END check_self;
2125    
2126     METHOD bound_all;
2127     RUN bound_self;
2128     END bound_all;
2129    
2130     METHOD bound_self;
2131     fl1.boundwidth := boundwidth;
2132     vap.boundwidth := boundwidth;
2133     liq_bot.boundwidth := boundwidth;
2134     vap_bot.boundwidth := boundwidth;
2135     liqin.boundwidth := boundwidth;
2136     RUN fl1.bound_all;
2137     END bound_self;
2138    
2139     METHOD scale_self;
2140     RUN liqin.scale_self;
2141     RUN vap.scale_self;
2142     RUN vap_bot.scale_self;
2143     RUN liq_bot.scale_self;
2144     RUN fl1.scale_self;
2145     END scale_self;
2146    
2147     METHOD specify;
2148     RUN fl1.specify;
2149     END specify;
2150    
2151     METHOD values;
2152     liqin.P := 1 {atm};
2153     liqin.T := 365 {K};
2154     liqin.f['methanol'] := 0.01 {kmol/s};
2155     liqin.f['ethanol'] := 0.015 {kmol/s};
2156     liqin.f['water'] := 0.02 {kmol/s};
2157     fl1.reboil_ratio :=1;
2158     fl1.P := 1 {atm};
2159     fl1.T := 365 {K};
2160     fl1.Qin := 0 {kW};
2161     fl1.Vol := 3 {m^3};
2162     fl1.vol_liq :=1 {m^3};
2163     END values;
2164     END test_reboiler;
2165    
2166    
2167     MODEL test_detailed_tray() REFINES testflashmodel();
2168    
2169     cd IS_A components_data(['methanol','ethanol','water'],'water');
2170     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
2171     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
2172     equilibrated IS_A boolean;
2173     vin IS_A stream(cd,pdV,equilibrated);
2174     lin IS_A stream(cd,pdL,equilibrated);
2175     lout IS_A stream(cd,pdL,equilibrated);
2176     vout IS_A stream(cd,pdV,equilibrated);
2177     pdVL IS_A phases_data('VL', vout.pd.vapor_option,
2178     lout.pd.liquid1_option, 'none');
2179     phaseVL[VLphases] ALIASES
2180     (vout.phase['vapor'],lout.phase['liquid1'])
2181     WHERE VLphases IS_A set OF symbol_constant
2182     WITH_VALUE ('vapor','liquid1');
2183     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
2184     t IS_A time;
2185     dynamic IS_A boolean;
2186     ode_offset IS_A ode_counter;
2187     obs_offset IS_A obs_counter;
2188     fl1 IS_A detailed_tray(lin.Details,vin.Details,lout.Details,vout.Details,
2189     state,t,dynamic,ode_offset,obs_offset);
2190    
2191     (* boundwidth might be unit specific *)
2192     boundwidth IS_A bound_width;
2193    
2194     METHODS
2195    
2196     METHOD default_all;
2197     RUN default_self;
2198     END default_all;
2199    
2200     METHOD default_self;
2201     boundwidth := 10;
2202     equilibrated :=TRUE;
2203     ode_offset :=1;
2204     obs_offset :=1;
2205     RUN vin.default_self;
2206     RUN lin.default_self;
2207     RUN lout.default_self;
2208     RUN vout.default_self;
2209     RUN fl1.default_self;
2210     END default_self;
2211    
2212     METHOD check_all;
2213     RUN check_self;
2214     END check_all;
2215    
2216     METHOD check_self;
2217     RUN vin.check_self;
2218     RUN lin.check_self;
2219     RUN lout.check_self;
2220     RUN vout.check_self;
2221     RUN fl1.check_self;
2222     END check_self;
2223    
2224     METHOD bound_all;
2225     RUN bound_self;
2226     END bound_all;
2227    
2228     METHOD bound_self;
2229     fl1.boundwidth := boundwidth;
2230     lin.boundwidth := boundwidth;
2231     vin.boundwidth := boundwidth;
2232     lout.boundwidth := boundwidth;
2233     vout.boundwidth := boundwidth;
2234     RUN fl1.bound_all;
2235     END bound_self;
2236    
2237     METHOD scale_self;
2238     RUN vin.scale_self;
2239     RUN lin.scale_self;
2240     RUN lout.scale_self;
2241     RUN vout.scale_self;
2242     RUN fl1.scale_self;
2243     END scale_self;
2244    
2245     METHOD specify;
2246     RUN fl1.specify;
2247     END specify;
2248    
2249     METHOD values;
2250     vin.P := 1 {atm};
2251     vin.T := 365 {K};
2252     vin.f['methanol'] := 0.01 {kmol/s};
2253     vin.f['ethanol'] := 0.015 {kmol/s};
2254     vin.f['water'] := 0.02 {kmol/s};
2255     lin.P := 1 {atm};
2256     lin.T := 365 {K};
2257     lin.f['methanol'] := 0.01 {kmol/s};
2258     lin.f['ethanol'] := 0.015 {kmol/s};
2259     lin.f['water'] := 0.02 {kmol/s};
2260     fl1.cmo_ratio := 1;
2261     fl1.P := 1 {atm};
2262     fl1.T := 365 {K};
2263     fl1.Qin := 0 {kW};
2264     fl1.Vol := 10 {m^3};
2265     fl1.vol_liq := 3 {m^3};
2266     END values;
2267    
2268     END test_detailed_tray;

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