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

Contents of /trunk/models/dyn_flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


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

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