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

Annotation of /trunk/models/dyn_flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


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

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