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

Annotation of /trunk/models/dyn_flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 669 - (hide annotations) (download) (as text)
Wed Jun 21 07:00:45 2006 UTC (17 years, 11 months ago) by johnpye
File MIME type: text/x-ascend
File size: 60792 byte(s)
Merged changes from DAE branch (revisions 702 to 819) back into trunk.
This adds the Integration API to the ASCEND solver (in base/generic).
Also provides pre-alpha support for 'IDA' from the SUNDIALS suite, a DAE solver.
Many other minor code clean-ups, including adoption of new 'ASC_NEW' and friends (to replace 'ascmalloc')
Added some very sketchy stuff providing 'DIFF(...)' syntax, although it is anticipated that this will be removed.
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 johnpye 576 FREE state.y[cd.components];
253 aw0a 1 IF equilibrated THEN
254 johnpye 576 FREE state.T;
255 aw0a 1 ELSE
256 johnpye 576 FIX state.T;
257 aw0a 1 END IF;
258 johnpye 576 FIX split_fraction['vapor'];
259     FREE state.phase_fraction['vapor'];
260     FIX dMi_dt[cd.other_components];
261     FREE Mi[cd.components];
262     FIX dM_dt;
263     FREE M;
264     FIX dU_dt;
265     FREE U;
266     FIX Vol;
267     FIX vol_liq;
268 aw0a 1 IF dynamic THEN
269 johnpye 576 FREE dMi_dt[cd.other_components];
270     FIX Mi[cd.other_components];
271     FREE dM_dt;
272     FIX M;
273     FREE dU_dt;
274     FIX U;
275     FIX Qin;
276 aw0a 1 IF equilibrated THEN
277 johnpye 576 FREE state.P;
278 aw0a 1 ELSE
279 johnpye 576 FREE state.T;
280 aw0a 1 END IF;
281 johnpye 576 FREE vol_liq;
282     FIX liqout.flow;
283     FIX vapout.flow;
284     FREE split_fraction['vapor'];
285 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
513 aw0a 1 IF equilibrated THEN
514 johnpye 576 FREE state.T;
515 aw0a 1 ELSE
516 johnpye 576 FIX state.T;
517 aw0a 1 END IF;
518 johnpye 576 FREE state.phase_fraction['vapor'];
519     FIX cmo_ratio;
520     FIX dMi_dt[cd.other_components];
521     FREE Mi[cd.other_components];
522     FIX dM_dt;
523     FREE M;
524     FIX dU_dt;
525     FREE U;
526     FIX Vol;
527     FIX vol_liq;
528     FREE tauv;
529     FREE taul;
530     FREE liqout.flow;
531     FREE vapout.flow;
532 aw0a 1 IF dynamic THEN
533 johnpye 576 FREE dMi_dt[cd.other_components];
534     FIX Mi[cd.other_components];
535     FREE dM_dt;
536     FIX M;
537     FREE dU_dt;
538     FIX U;
539     FIX Qin;
540 aw0a 1 IF equilibrated THEN
541 johnpye 576 FREE state.P;
542 aw0a 1 ELSE
543 johnpye 576 FREE state.T;
544 aw0a 1 END IF;
545 johnpye 576 FREE vol_liq;
546     FIX tauv;
547     FIX taul;
548     FREE cmo_ratio;
549 aw0a 1 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 johnpye 576 FREE cmo_ratio;
564     FIX Qin;
565 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
955 aw0a 1 IF equilibrated THEN
956 johnpye 576 FREE state.T;
957 aw0a 1 ELSE
958 johnpye 576 FIX state.T;
959 aw0a 1 END IF;
960 johnpye 576 FREE state.phase_fraction['vapor'];
961     FIX q;
962     FIX dMi_dt[cd.other_components];
963     FREE Mi[cd.other_components];
964     FIX dM_dt;
965     FREE M;
966     FIX dU_dt;
967     FREE U;
968     FIX Vol;
969     FIX vol_liq;
970     FREE tauv;
971     FREE taul;
972 aw0a 1 IF dynamic THEN
973 johnpye 576 FREE dMi_dt[cd.other_components];
974     FIX Mi[cd.other_components];
975     FREE dM_dt;
976     FIX M;
977     FREE dU_dt;
978     FIX U;
979     FIX Qin;
980 aw0a 1 IF equilibrated THEN
981 johnpye 576 FREE state.P;
982 aw0a 1 ELSE
983 johnpye 576 FREE state.T;
984 aw0a 1 END IF;
985 johnpye 576 FREE vol_liq;
986     FIX tauv;
987     FIX taul;
988     FREE q;
989 aw0a 1 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 johnpye 576 FREE q;
1006     FIX Qin;
1007 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
1249     FREE state.phase_fraction['vapor'];
1250 aw0a 1 IF equilibrated THEN
1251 johnpye 576 FREE state.T;
1252 aw0a 1 ELSE
1253 johnpye 576 FIX state.T;
1254 aw0a 1 END IF;
1255     RUN split.seqmod;
1256 johnpye 576 FREE split.split[1];
1257     FREE liqout.flow;
1258     FREE vap_distillate.flow;
1259     FREE liq_distillate.flow;
1260 aw0a 1 IF partial THEN
1261 johnpye 576 FIX liq_distillate.flow;
1262 aw0a 1 ELSE
1263 johnpye 576 FIX vap_distillate.flow;
1264 aw0a 1 END IF;
1265 johnpye 576 FIX reflux_ratio;
1266     FIX dMi_dt[cd.other_components];
1267     FREE Mi[cd.other_components];
1268     FIX dM_dt;
1269     FREE M;
1270     FIX dU_dt;
1271     FREE U;
1272     FREE Qin;
1273     FIX Vol;
1274     FIX vol_liq;
1275 aw0a 1 IF dynamic THEN
1276 johnpye 576 FREE dMi_dt[cd.other_components];
1277     FIX Mi[cd.other_components];
1278     FREE dM_dt;
1279     FIX M;
1280     FREE dU_dt;
1281     FIX U;
1282     FIX Qin;
1283 aw0a 1 IF equilibrated THEN
1284 johnpye 576 FREE state.P;
1285 aw0a 1 ELSE
1286 johnpye 576 FREE state.T;
1287 aw0a 1 END IF;
1288 johnpye 576 FREE vol_liq;
1289     FREE reflux_ratio;
1290     FREE state.phase_fraction['vapor'];
1291     FIX liqout.flow;
1292     (* FIX liqout.Details.state.slack_PhaseDisappearance['liquid1'];*)
1293     FIX vap_distillate.flow;
1294     FIX liq_distillate.flow;
1295 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
1546     FREE state.phase_fraction['vapor'];
1547 aw0a 1 IF equilibrated THEN
1548 johnpye 576 FREE state.T;
1549 aw0a 1 ELSE
1550 johnpye 576 FIX state.T;
1551 aw0a 1 END IF;
1552     RUN split.seqmod;
1553 johnpye 576 FREE split.split[1];
1554     FREE vapout.flow;
1555     FREE vap_bottom.flow;
1556     FREE liq_bottom.flow;
1557 aw0a 1 IF partial THEN
1558 johnpye 576 FIX vap_bottom.flow;
1559 aw0a 1 ELSE
1560 johnpye 576 FIX liq_bottom.flow;
1561 aw0a 1 END IF;
1562 johnpye 576 FIX reboil_ratio;
1563     FIX dMi_dt[cd.other_components];
1564     FREE Mi[cd.other_components];
1565     FIX dM_dt;
1566     FREE M;
1567     FIX dU_dt;
1568     FREE U;
1569     FREE Qin;
1570     FIX Vol;
1571     FIX vol_liq;
1572 aw0a 1 IF dynamic THEN
1573 johnpye 576 FREE dMi_dt[cd.other_components];
1574     FIX Mi[cd.other_components];
1575     FREE dM_dt;
1576     FIX M;
1577     FREE dU_dt;
1578     FIX U;
1579     FIX Qin;
1580 aw0a 1 IF equilibrated THEN
1581 johnpye 576 FREE state.P;
1582 aw0a 1 ELSE
1583 johnpye 576 FREE state.T;
1584 aw0a 1 END IF;
1585 johnpye 576 FREE vol_liq;
1586     FREE reboil_ratio;
1587     FREE state.phase_fraction['vapor'];
1588     FIX vapout.flow;
1589     FIX vap_bottom.flow;
1590     FIX liq_bottom.flow;
1591 aw0a 1 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 johnpye 669 (* root for flash based test models *)
1644 aw0a 1 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 johnpye 669
1747     METHOD on_load;
1748     RUN default_self;
1749     equilibrated := FALSE;
1750     RUN values; RUN reset;
1751     END on_load;
1752    
1753     METHOD prepare_ode;
1754     (* solve *)
1755     RUN check_self;
1756     dynamic := TRUE;
1757     RUN fl1.seqmod;
1758     RUN fl1.set_ode;
1759     RUN fl1.set_obs;
1760     END prepare_ode;
1761    
1762 aw0a 1 END test_vapor_liquid_flash;
1763    
1764    
1765     MODEL test_tray() REFINES testflashmodel();
1766    
1767     (* the next 5 are probably used throughout a flowsheet *)
1768     cd IS_A components_data(['methanol','ethanol','water'],'water');
1769     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1770     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1771    
1772     equilibrated IS_A boolean;
1773     vin IS_A stream(cd, pdV, equilibrated);
1774     lin IS_A stream(cd, pdL, equilibrated);
1775     lout IS_A stream(cd, pdL, equilibrated);
1776     vout IS_A stream(cd, pdV, equilibrated);
1777     t IS_A time;
1778     dynamic IS_A boolean;
1779     ode_offset IS_A ode_counter;
1780     obs_offset IS_A obs_counter;
1781     fl1 IS_A tray(lin,vin,lout,vout,t,dynamic,ode_offset,obs_offset);
1782    
1783     (* boundwidth might be unit specific *)
1784     boundwidth IS_A bound_width;
1785    
1786     METHODS
1787    
1788     METHOD default_all;
1789     RUN default_self;
1790     END default_all;
1791    
1792     METHOD default_self;
1793     boundwidth := 10;
1794     equilibrated :=TRUE;
1795     ode_offset :=1;
1796     obs_offset :=1;
1797     RUN vin.default_self;
1798     RUN lin.default_self;
1799     RUN lout.default_self;
1800     RUN vout.default_self;
1801     RUN fl1.default_self;
1802     (* or could be RUN fl1.default_all; *)
1803     END default_self;
1804    
1805     METHOD check_all;
1806     RUN check_self;
1807     END check_all;
1808    
1809     METHOD check_self;
1810     RUN vin.check_self;
1811     RUN lin.check_self;
1812     RUN lout.check_self;
1813     RUN vout.check_self;
1814     RUN fl1.check_self;
1815     (* or could be RUN check_all; *)
1816     END check_self;
1817    
1818     METHOD bound_all;
1819     RUN bound_self;
1820     END bound_all;
1821    
1822     METHOD bound_self;
1823     fl1.boundwidth := boundwidth;
1824     lin.boundwidth := boundwidth;
1825     vin.boundwidth := boundwidth;
1826     lout.boundwidth := boundwidth;
1827     vout.boundwidth := boundwidth;
1828     (* The right, later reusable, way to finish this method is as follows:
1829     RUN vin.bound_self
1830     RUN lin.bound_self;
1831     RUN lout.bound_self;
1832     RUN vout.bound_self;
1833     RUN fl1.bound_self;
1834     * where we didn't have to look inside the parts we're using because
1835     * we know they follow the standard in system.a4l.
1836     *)
1837     (* The quick and dirty way, since there are no parts passed into
1838     * this MODEL is like so:
1839     *)
1840     RUN fl1.bound_all;
1841     (* This works, but we had to look into the VLflash MODEL to be sure. *)
1842     END bound_self;
1843    
1844     METHOD scale_self;
1845     RUN vin.scale_self;
1846     RUN lin.scale_self;
1847     RUN lout.scale_self;
1848     RUN vout.scale_self;
1849     RUN fl1.scale_self;
1850     (* or could be RUN fl1.scale_all; *)
1851     END scale_self;
1852    
1853     METHOD specify;
1854     RUN fl1.specify;
1855     END specify;
1856    
1857     METHOD values;
1858     vin.P := 1 {atm};
1859     vin.T := 365 {K};
1860     vin.f['methanol'] := 0.01 {kmol/s};
1861     vin.f['ethanol'] := 0.015 {kmol/s};
1862     vin.f['water'] := 0.02 {kmol/s};
1863     lin.P := 1 {atm};
1864     lin.T := 365 {K};
1865     lin.f['methanol'] := 0.01 {kmol/s};
1866     lin.f['ethanol'] := 0.015 {kmol/s};
1867     lin.f['water'] := 0.02 {kmol/s};
1868     fl1.cmo_ratio := 1;
1869     fl1.P := 1 {atm};
1870     fl1.T := 365 {K};
1871     fl1.Qin := 0 {kW};
1872     fl1.Vol := 10 {m^3};
1873     fl1.vol_liq := 3 {m^3};
1874     END values;
1875    
1876     END test_tray;
1877    
1878    
1879     MODEL test_feed_tray() REFINES testflashmodel();
1880    
1881     (* the next 5 are probably used throughout a flowsheet *)
1882     cd IS_A components_data(['methanol','ethanol','water'],'water');
1883     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1884     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1885    
1886     equilibrated IS_A boolean;
1887     feed IS_A stream(cd, pdV, equilibrated);
1888     vin IS_A stream(cd, pdV, equilibrated);
1889     lin IS_A stream(cd, pdL, equilibrated);
1890     lout IS_A stream(cd, pdL, equilibrated);
1891     vout IS_A stream(cd, pdV, equilibrated);
1892     t IS_A time;
1893     dynamic IS_A boolean;
1894     ode_offset IS_A ode_counter;
1895     obs_offset IS_A obs_counter;
1896     fl1 IS_A feed_tray(feed,lin,vin,lout,vout,t,dynamic,ode_offset,obs_offset);
1897    
1898     (* boundwidth might be unit specific *)
1899     boundwidth IS_A bound_width;
1900    
1901     METHODS
1902    
1903     METHOD default_all;
1904     RUN default_self;
1905     END default_all;
1906    
1907     METHOD default_self;
1908     boundwidth := 10;
1909     equilibrated :=TRUE;
1910     ode_offset :=1;
1911     obs_offset :=1;
1912     RUN feed.default_self;
1913     RUN vin.default_self;
1914     RUN lin.default_self;
1915     RUN lout.default_self;
1916     RUN vout.default_self;
1917     RUN fl1.default_self;
1918     END default_self;
1919    
1920     METHOD check_all;
1921     RUN check_self;
1922     END check_all;
1923    
1924     METHOD check_self;
1925     RUN feed.check_self;
1926     RUN vin.check_self;
1927     RUN lin.check_self;
1928     RUN lout.check_self;
1929     RUN vout.check_self;
1930     RUN fl1.check_self;
1931     END check_self;
1932    
1933     METHOD bound_all;
1934     RUN bound_self;
1935     END bound_all;
1936    
1937     METHOD bound_self;
1938     fl1.boundwidth := boundwidth;
1939     feed.boundwidth := boundwidth;
1940     lin.boundwidth := boundwidth;
1941     vin.boundwidth := boundwidth;
1942     lout.boundwidth := boundwidth;
1943     vout.boundwidth := boundwidth;
1944     RUN fl1.bound_all;
1945     END bound_self;
1946    
1947     METHOD scale_self;
1948     RUN feed.scale_self;
1949     RUN vin.scale_self;
1950     RUN lin.scale_self;
1951     RUN lout.scale_self;
1952     RUN vout.scale_self;
1953     RUN fl1.scale_self;
1954     END scale_self;
1955    
1956     METHOD specify;
1957     RUN fl1.specify;
1958     END specify;
1959    
1960     METHOD values;
1961     feed.P := 1 {atm};
1962     feed.T := 365 {K};
1963     feed.f['methanol'] := 0.01 {kmol/s};
1964     feed.f['ethanol'] := 0.015 {kmol/s};
1965     feed.f['water'] := 0.02 {kmol/s};
1966     vin.P := 1 {atm};
1967     vin.T := 365 {K};
1968     vin.f['methanol'] := 0.01 {kmol/s};
1969     vin.f['ethanol'] := 0.015 {kmol/s};
1970     vin.f['water'] := 0.02 {kmol/s};
1971     lin.P := 1 {atm};
1972     lin.T := 365 {K};
1973     lin.f['methanol'] := 0.01 {kmol/s};
1974     lin.f['ethanol'] := 0.015 {kmol/s};
1975     lin.f['water'] := 0.02 {kmol/s};
1976     fl1.q := 0;
1977     fl1.P := 1 {atm};
1978     fl1.T := 365 {K};
1979     fl1.Qin := 0 {kW};
1980     fl1.Vol := 10 {m^3};
1981     fl1.vol_liq := 3 {m^3};
1982     END values;
1983     END test_feed_tray;
1984    
1985    
1986    
1987     MODEL test_condenser() REFINES testflashmodel();
1988    
1989     (* the next 5 are probably used throughout a flowsheet *)
1990     cd IS_A components_data(['methanol','ethanol','water'],'water');
1991     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
1992     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1993     partial IS_A boolean;
1994     equilibrated IS_A boolean;
1995     vapin IS_A stream(cd, pdV, equilibrated);
1996     liq IS_A stream(cd, pdL, equilibrated);
1997     liq_dist IS_A stream(cd, pdL, equilibrated);
1998     vap_dist IS_A stream(cd, pdV, equilibrated);
1999     t IS_A time;
2000     dynamic IS_A boolean;
2001     ode_offset IS_A ode_counter;
2002     obs_offset IS_A obs_counter;
2003     fl1 IS_A condenser(vapin,vap_dist,liq_dist,liq,partial,t,dynamic,
2004     ode_offset,obs_offset);
2005    
2006     (* boundwidth might be unit specific *)
2007     boundwidth IS_A bound_width;
2008    
2009     METHODS
2010    
2011     METHOD default_all;
2012     RUN default_self;
2013     END default_all;
2014    
2015     METHOD default_self;
2016     boundwidth := 10;
2017     equilibrated :=TRUE;
2018     ode_offset :=1;
2019     obs_offset :=1;
2020     RUN vapin.default_self;
2021     RUN liq.default_self;
2022     RUN vap_dist.default_self;
2023     RUN liq_dist.default_self;
2024     RUN fl1.default_self;
2025     (* or could be RUN fl1.default_all; *)
2026     END default_self;
2027    
2028     METHOD check_all;
2029     RUN check_self;
2030     END check_all;
2031    
2032     METHOD check_self;
2033     RUN vapin.check_self;
2034     RUN liq.check_self;
2035     IF partial THEN
2036     RUN vap_dist.check_self;
2037     ELSE
2038     RUN liq_dist.check_self;
2039     END IF;
2040     RUN fl1.check_self;
2041     (* or could be RUN fl1.check_all; *)
2042     END check_self;
2043    
2044     METHOD bound_all;
2045     RUN bound_self;
2046     END bound_all;
2047    
2048     METHOD bound_self;
2049     fl1.boundwidth := boundwidth;
2050     liq.boundwidth := boundwidth;
2051     liq_dist.boundwidth := boundwidth;
2052     vap_dist.boundwidth := boundwidth;
2053     vapin.boundwidth := boundwidth;
2054     RUN fl1.bound_all;
2055     END bound_self;
2056    
2057     METHOD scale_self;
2058     RUN vapin.scale_self;
2059     RUN liq.scale_self;
2060     RUN vap_dist.scale_self;
2061     RUN liq_dist.scale_self;
2062     RUN fl1.scale_self;
2063     END scale_self;
2064    
2065     METHOD specify;
2066     RUN fl1.specify;
2067     END specify;
2068    
2069     METHOD values;
2070     vapin.P := 1 {atm};
2071     vapin.T := 365 {K};
2072     vapin.f['methanol'] := 0.01 {kmol/s};
2073     vapin.f['ethanol'] := 0.015 {kmol/s};
2074     vapin.f['water'] := 0.02 {kmol/s};
2075     fl1.reflux_ratio :=1;
2076     fl1.P := 1 {atm};
2077     fl1.T := 365 {K};
2078     fl1.Qin := 0 {kW};
2079     fl1.Vol := 3 {m^3};
2080     fl1.vol_liq := 1 {m^3};
2081     END values;
2082     END test_condenser;
2083    
2084     MODEL test_reboiler() REFINES testflashmodel();
2085    
2086     (* the next 5 are probably used throughout a flowsheet *)
2087     cd IS_A components_data(['methanol','ethanol','water'],'water');
2088     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
2089     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
2090     partial IS_A boolean;
2091     equilibrated IS_A boolean;
2092     liqin IS_A stream(cd, pdL, equilibrated);
2093     vap IS_A stream(cd, pdV, equilibrated);
2094     liq_bot IS_A stream(cd, pdL, equilibrated);
2095     vap_bot IS_A stream(cd, pdV, equilibrated);
2096     t IS_A time;
2097     dynamic IS_A boolean;
2098     ode_offset IS_A ode_counter;
2099     obs_offset IS_A obs_counter;
2100     fl1 IS_A reboiler(liqin,vap_bot,liq_bot,vap,partial,t,dynamic,
2101     ode_offset,obs_offset);
2102    
2103     (* boundwidth might be unit specific *)
2104     boundwidth IS_A bound_width;
2105    
2106     METHODS
2107    
2108     METHOD default_all;
2109     RUN default_self;
2110     END default_all;
2111    
2112     METHOD default_self;
2113     boundwidth := 10;
2114     equilibrated :=TRUE;
2115     partial :=FALSE;
2116     ode_offset :=1;
2117     obs_offset :=1;
2118     RUN liqin.default_self;
2119     RUN vap.default_self;
2120     RUN vap_bot.default_self;
2121     RUN liq_bot.default_self;
2122     RUN fl1.default_self;
2123     (* or could be RUN fl1.default_all; *)
2124     END default_self;
2125    
2126     METHOD check_all;
2127     RUN check_self;
2128     END check_all;
2129    
2130     METHOD check_self;
2131     RUN liqin.check_self;
2132     RUN vap.check_self;
2133     IF partial THEN
2134     RUN liq_bot.check_self;
2135     ELSE
2136     RUN vap_bot.check_self;
2137     END IF;
2138     RUN fl1.check_self;
2139     (* or could be RUN check_all; *)
2140     END check_self;
2141    
2142     METHOD bound_all;
2143     RUN bound_self;
2144     END bound_all;
2145    
2146     METHOD bound_self;
2147     fl1.boundwidth := boundwidth;
2148     vap.boundwidth := boundwidth;
2149     liq_bot.boundwidth := boundwidth;
2150     vap_bot.boundwidth := boundwidth;
2151     liqin.boundwidth := boundwidth;
2152     RUN fl1.bound_all;
2153     END bound_self;
2154    
2155     METHOD scale_self;
2156     RUN liqin.scale_self;
2157     RUN vap.scale_self;
2158     RUN vap_bot.scale_self;
2159     RUN liq_bot.scale_self;
2160     RUN fl1.scale_self;
2161     END scale_self;
2162    
2163     METHOD specify;
2164     RUN fl1.specify;
2165     END specify;
2166    
2167     METHOD values;
2168     liqin.P := 1 {atm};
2169     liqin.T := 365 {K};
2170     liqin.f['methanol'] := 0.01 {kmol/s};
2171     liqin.f['ethanol'] := 0.015 {kmol/s};
2172     liqin.f['water'] := 0.02 {kmol/s};
2173     fl1.reboil_ratio :=1;
2174     fl1.P := 1 {atm};
2175     fl1.T := 365 {K};
2176     fl1.Qin := 0 {kW};
2177     fl1.Vol := 3 {m^3};
2178     fl1.vol_liq :=1 {m^3};
2179     END values;
2180     END test_reboiler;
2181    
2182    
2183     MODEL test_detailed_tray() REFINES testflashmodel();
2184    
2185     cd IS_A components_data(['methanol','ethanol','water'],'water');
2186     pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none');
2187     pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
2188     equilibrated IS_A boolean;
2189     vin IS_A stream(cd,pdV,equilibrated);
2190     lin IS_A stream(cd,pdL,equilibrated);
2191     lout IS_A stream(cd,pdL,equilibrated);
2192     vout IS_A stream(cd,pdV,equilibrated);
2193     pdVL IS_A phases_data('VL', vout.pd.vapor_option,
2194     lout.pd.liquid1_option, 'none');
2195     phaseVL[VLphases] ALIASES
2196     (vout.phase['vapor'],lout.phase['liquid1'])
2197     WHERE VLphases IS_A set OF symbol_constant
2198     WITH_VALUE ('vapor','liquid1');
2199     state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
2200     t IS_A time;
2201     dynamic IS_A boolean;
2202     ode_offset IS_A ode_counter;
2203     obs_offset IS_A obs_counter;
2204     fl1 IS_A detailed_tray(lin.Details,vin.Details,lout.Details,vout.Details,
2205     state,t,dynamic,ode_offset,obs_offset);
2206    
2207     (* boundwidth might be unit specific *)
2208     boundwidth IS_A bound_width;
2209    
2210     METHODS
2211    
2212     METHOD default_all;
2213     RUN default_self;
2214     END default_all;
2215    
2216     METHOD default_self;
2217     boundwidth := 10;
2218     equilibrated :=TRUE;
2219     ode_offset :=1;
2220     obs_offset :=1;
2221     RUN vin.default_self;
2222     RUN lin.default_self;
2223     RUN lout.default_self;
2224     RUN vout.default_self;
2225     RUN fl1.default_self;
2226     END default_self;
2227    
2228     METHOD check_all;
2229     RUN check_self;
2230     END check_all;
2231    
2232     METHOD check_self;
2233     RUN vin.check_self;
2234     RUN lin.check_self;
2235     RUN lout.check_self;
2236     RUN vout.check_self;
2237     RUN fl1.check_self;
2238     END check_self;
2239    
2240     METHOD bound_all;
2241     RUN bound_self;
2242     END bound_all;
2243    
2244     METHOD bound_self;
2245     fl1.boundwidth := boundwidth;
2246     lin.boundwidth := boundwidth;
2247     vin.boundwidth := boundwidth;
2248     lout.boundwidth := boundwidth;
2249     vout.boundwidth := boundwidth;
2250     RUN fl1.bound_all;
2251     END bound_self;
2252    
2253     METHOD scale_self;
2254     RUN vin.scale_self;
2255     RUN lin.scale_self;
2256     RUN lout.scale_self;
2257     RUN vout.scale_self;
2258     RUN fl1.scale_self;
2259     END scale_self;
2260    
2261     METHOD specify;
2262     RUN fl1.specify;
2263     END specify;
2264    
2265     METHOD values;
2266     vin.P := 1 {atm};
2267     vin.T := 365 {K};
2268     vin.f['methanol'] := 0.01 {kmol/s};
2269     vin.f['ethanol'] := 0.015 {kmol/s};
2270     vin.f['water'] := 0.02 {kmol/s};
2271     lin.P := 1 {atm};
2272     lin.T := 365 {K};
2273     lin.f['methanol'] := 0.01 {kmol/s};
2274     lin.f['ethanol'] := 0.015 {kmol/s};
2275     lin.f['water'] := 0.02 {kmol/s};
2276     fl1.cmo_ratio := 1;
2277     fl1.P := 1 {atm};
2278     fl1.T := 365 {K};
2279     fl1.Qin := 0 {kW};
2280     fl1.Vol := 10 {m^3};
2281     fl1.vol_liq := 3 {m^3};
2282     END values;
2283    
2284     END test_detailed_tray;

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