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

Contents of /trunk/models/dyn_flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2651 - (show 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 (* 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 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *)
18 REQUIRE "ivpsystem.a4l";
19 REQUIRE "splitter.a4l";
20 (*
21 dyn_flash.a4l by by Duncan Coffey (modified from flash.a4l by Ben Allan)
22 *)
23
24 MODEL flash_base REFINES cmumodel;
25 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
43 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 cd ALIASES feed.cd;
79 P ALIASES liqout.P;
80 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 FREE state.y[cd.components];
236 IF equilibrated THEN
237 FREE state.T;
238 ELSE
239 FIX state.T;
240 END IF;
241 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 IF dynamic THEN
252 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 IF equilibrated THEN
260 FREE state.P;
261 ELSE
262 FREE state.T;
263 END IF;
264 FREE vol_liq;
265 FIX liqout.flow;
266 FIX vapout.flow;
267 FREE split_fraction['vapor'];
268 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 cd ALIASES vapout.state.cd;
357 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 FREE state.y[cd.components];
496 IF equilibrated THEN
497 FREE state.T;
498 ELSE
499 FIX state.T;
500 END IF;
501 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 IF dynamic THEN
516 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 IF equilibrated THEN
524 FREE state.P;
525 ELSE
526 FREE state.T;
527 END IF;
528 FREE vol_liq;
529 FIX tauv;
530 FIX taul;
531 FREE cmo_ratio;
532 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 FREE cmo_ratio;
547 FIX Qin;
548 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 METHODS
842 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 FREE state.y[cd.components];
938 IF equilibrated THEN
939 FREE state.T;
940 ELSE
941 FIX state.T;
942 END IF;
943 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 IF dynamic THEN
956 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 IF equilibrated THEN
964 FREE state.P;
965 ELSE
966 FREE state.T;
967 END IF;
968 FREE vol_liq;
969 FIX tauv;
970 FIX taul;
971 FREE q;
972 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 FREE q;
989 FIX Qin;
990 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 FREE state.y[cd.components];
1232 FREE state.phase_fraction['vapor'];
1233 IF equilibrated THEN
1234 FREE state.T;
1235 ELSE
1236 FIX state.T;
1237 END IF;
1238 RUN split.seqmod;
1239 FREE split.split[1];
1240 FREE liqout.flow;
1241 FREE vap_distillate.flow;
1242 FREE liq_distillate.flow;
1243 IF partial THEN
1244 FIX liq_distillate.flow;
1245 ELSE
1246 FIX vap_distillate.flow;
1247 END IF;
1248 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 IF dynamic THEN
1259 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 IF equilibrated THEN
1267 FREE state.P;
1268 ELSE
1269 FREE state.T;
1270 END IF;
1271 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 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 FREE state.y[cd.components];
1529 FREE state.phase_fraction['vapor'];
1530 IF equilibrated THEN
1531 FREE state.T;
1532 ELSE
1533 FIX state.T;
1534 END IF;
1535 RUN split.seqmod;
1536 FREE split.split[1];
1537 FREE vapout.flow;
1538 FREE vap_bottom.flow;
1539 FREE liq_bottom.flow;
1540 IF partial THEN
1541 FIX vap_bottom.flow;
1542 ELSE
1543 FIX liq_bottom.flow;
1544 END IF;
1545 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 IF dynamic THEN
1556 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 IF equilibrated THEN
1564 FREE state.P;
1565 ELSE
1566 FREE state.T;
1567 END IF;
1568 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 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 (* root for flash based test models *)
1627 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
1650 METHODS
1651 METHOD default_all;
1652 RUN default_self;
1653 END default_all;
1654
1655 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
1667 METHOD check_all;
1668 RUN check_self;
1669 END check_all;
1670
1671 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
1679 METHOD bound_all;
1680 RUN bound_self;
1681 END bound_all;
1682
1683 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
1703 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
1711 METHOD specify;
1712 RUN fl1.specify;
1713 END specify;
1714
1715 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
1729 METHOD on_load;
1730 RUN default_self;
1731 equilibrated := FALSE;
1732 RUN values; RUN reset;
1733 END on_load;
1734
1735 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
1744 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 METHOD default_all;
1770 RUN default_self;
1771 END default_all;
1772
1773 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
1786 METHOD check_all;
1787 RUN check_self;
1788 END check_all;
1789
1790 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
1799 METHOD bound_all;
1800 RUN bound_self;
1801 END bound_all;
1802
1803 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
1825 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
1834 METHOD specify;
1835 RUN fl1.specify;
1836 END specify;
1837
1838 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 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 METHOD default_all;
1883 RUN default_self;
1884 END default_all;
1885
1886 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
1899 METHOD check_all;
1900 RUN check_self;
1901 END check_all;
1902
1903 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
1912 METHOD bound_all;
1913 RUN bound_self;
1914 END bound_all;
1915
1916 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
1926 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
1935 METHOD specify;
1936 RUN fl1.specify;
1937 END specify;
1938
1939 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 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 METHOD default_all;
1990 RUN default_self;
1991 END default_all;
1992
1993 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
2006 METHOD check_all;
2007 RUN check_self;
2008 END check_all;
2009
2010 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
2022 METHOD bound_all;
2023 RUN bound_self;
2024 END bound_all;
2025
2026 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
2035 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
2043 METHOD specify;
2044 RUN fl1.specify;
2045 END specify;
2046
2047 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 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 METHOD default_all;
2086 RUN default_self;
2087 END default_all;
2088
2089 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
2103 METHOD check_all;
2104 RUN check_self;
2105 END check_all;
2106
2107 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
2119 METHOD bound_all;
2120 RUN bound_self;
2121 END bound_all;
2122
2123 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
2132 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
2140 METHOD specify;
2141 RUN fl1.specify;
2142 END specify;
2143
2144 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 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 METHOD default_all;
2189 RUN default_self;
2190 END default_all;
2191
2192 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
2204 METHOD check_all;
2205 RUN check_self;
2206 END check_all;
2207
2208 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
2216 METHOD bound_all;
2217 RUN bound_self;
2218 END bound_all;
2219
2220 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
2229 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
2237 METHOD specify;
2238 RUN fl1.specify;
2239 END specify;
2240
2241 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 END test_detailed_tray;

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