1 |
REQUIRE "flash.a4l"; |
2 |
(* => flash.a4l, stream_holdup.a4l, thermodynamics.a4l, components.a4l, |
3 |
* phases.a4l, atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *) |
4 |
PROVIDE "column.a4l"; |
5 |
|
6 |
(* |
7 |
* column.a4l |
8 |
* by Ben Allan, Art Westerberg, and Jennifer Perry |
9 |
* Part of the ASCEND Library |
10 |
* $Date: 1998/06/17 18:50:36 $ |
11 |
* $Revision: 1.5 $ |
12 |
* $Author: mthomas $ |
13 |
* $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/column.a4l,v $ |
14 |
* |
15 |
* This file is part of the ASCEND Modeling Library. |
16 |
* It defines basic tray-by-tray steady-state distillation models. |
17 |
* |
18 |
* Copyright (C) 1997,1998 Carnegie Mellon University |
19 |
* |
20 |
* The ASCEND Modeling Library is free software; you can redistribute |
21 |
* it and/or modify it under the terms of the GNU General Public |
22 |
* License as published by the Free Software Foundation; either |
23 |
* version 2 of the License, or (at your option) any later version. |
24 |
* |
25 |
* The ASCEND Modeling Library is distributed in hope that it |
26 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
27 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
28 |
* See the GNU General Public License for more details. |
29 |
* |
30 |
* You should have received a copy of the GNU General Public License |
31 |
* along with the program; if not, write to the Free Software |
32 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
33 |
* the file named COPYING. |
34 |
*) |
35 |
|
36 |
MODEL colmodel() REFINES cmumodel(); |
37 |
boundwidth IS_A bound_width; |
38 |
END colmodel; |
39 |
|
40 |
MODEL tray_stack( |
41 |
n_trays WILL_BE integer_constant; |
42 |
vapout WILL_BE stream; |
43 |
liqin WILL_BE stream; |
44 |
vapin WILL_BE stream; |
45 |
liqout WILL_BE stream; |
46 |
reduce WILL_BE fraction; |
47 |
equilibrated WILL_BE boolean; |
48 |
) WHERE ( |
49 |
n_trays > 1; |
50 |
vapout, liqin, vapin, liqout WILL_NOT_BE_THE_SAME; |
51 |
vapout.cd, vapin.cd, liqout.cd, liqin.cd WILL_BE_THE_SAME; |
52 |
vapout.pd, vapin.pd WILL_BE_THE_SAME; |
53 |
liqout.pd, liqin.pd WILL_BE_THE_SAME; |
54 |
liqout.pd.phase_indicator == 'L'; |
55 |
vapin.pd.phase_indicator == 'V'; |
56 |
liqin.pd.phase_indicator == 'L'; |
57 |
vapout.pd.phase_indicator == 'V'; |
58 |
) REFINES colmodel(); |
59 |
|
60 |
NOTES 'ascii-picture' |
61 |
SELF { |
62 |
vapout ^ | |
63 |
| v liqin |
64 |
+---+ |
65 |
|_1_| |
66 |
|___| n_trays (at least 2) |
67 |
|___| |
68 |
|_n_| |
69 |
vapin ^ | |
70 |
| v liqout |
71 |
} |
72 |
'usage' |
73 |
equilibrated { |
74 |
When TRUE, enforces equilbrium between phases on all the trays. |
75 |
When FALSE, uses constant alpha between phases on all the trays. |
76 |
} |
77 |
reduce { |
78 |
Homotopy parameter used by reduce_Q to move fixed errors in the |
79 |
energy balances (Qin per tray) toward 0. |
80 |
} |
81 |
'contra-indications' SELF { |
82 |
For a n==1 tray stack, use a "tray" MODEL from the flash library. |
83 |
} |
84 |
END NOTES; |
85 |
|
86 |
cd ALIASES liqout.cd; |
87 |
pdL ALIASES liqout.pd; |
88 |
pdV ALIASES vapout.pd; |
89 |
vap_option ALIASES pdV.vapor_option; |
90 |
liq_option ALIASES pdL.liquid1_option; |
91 |
pdVL IS_A phases_data('VL', vap_option, liq_option, 'none'); |
92 |
|
93 |
(* |
94 |
* The ALIASES/IS_A break if the liqout,vapout are on the same tray. |
95 |
*) |
96 |
|
97 |
Tray_set IS_A set OF integer_constant; |
98 |
Tray_set :== [1..n_trays]; |
99 |
|
100 |
components ALIASES cd.components; |
101 |
phases ALIASES pdVL.phases; |
102 |
|
103 |
(* there are alternative ways of building repeated structures. |
104 |
* This is the first one I came up with. It may not be the best. |
105 |
* BAA. |
106 |
*) |
107 |
|
108 |
(* build the internal phase mixing rules, and interior stream |
109 |
* states, and interior streams. |
110 |
*) |
111 |
internal_liquid_mixture[1..n_trays-1] |
112 |
IS_A select_mixture_type(cd, liq_option); |
113 |
FOR k IN [1..n_trays-1] CREATE |
114 |
internal_liquid_phase[k]['liquid1'] ALIASES |
115 |
internal_liquid_mixture[k].phase; |
116 |
END FOR; |
117 |
FOR k IN [1..n_trays-1] CREATE |
118 |
internal_liquid_state[k] IS_A |
119 |
thermodynamics(cd, pdL, internal_liquid_phase[k], equilibrated); |
120 |
END FOR; |
121 |
FOR k IN [1..n_trays-1] CREATE |
122 |
internal_liquid_stream[k] IS_A |
123 |
detailed_stream(internal_liquid_state[k]); |
124 |
END FOR; |
125 |
internal_vapor_mixture[2..n_trays] |
126 |
IS_A select_mixture_type(cd, vap_option); |
127 |
FOR k IN [2..n_trays] CREATE |
128 |
internal_vapor_phase[k]['vapor'] ALIASES |
129 |
internal_vapor_mixture[k].phase; |
130 |
END FOR; |
131 |
FOR k IN [2..n_trays] CREATE |
132 |
internal_vapor_state[k] IS_A |
133 |
thermodynamics(cd, pdV, internal_vapor_phase[k], equilibrated); |
134 |
END FOR; |
135 |
FOR k IN [2..n_trays] CREATE |
136 |
internal_vapor_stream[k] IS_A |
137 |
detailed_stream(internal_vapor_state[k]); |
138 |
END FOR; |
139 |
|
140 |
(* build tray VLE objects *) |
141 |
|
142 |
(* assemble into intermediate, easily accessed arrays *) |
143 |
tray_liquid_mixture[tlTrays] ALIASES |
144 |
(internal_liquid_mixture[1..n_trays-1].phase, |
145 |
liqout.smt['liquid1'].phase) |
146 |
WHERE tlTrays IS_A set OF integer_constant |
147 |
WITH_VALUE (1..n_trays); |
148 |
tray_vapor_mixture[tvTrays] ALIASES |
149 |
(vapout.smt['vapor'].phase, |
150 |
internal_vapor_mixture[2..n_trays].phase) |
151 |
WHERE tvTrays IS_A set OF integer_constant |
152 |
WITH_VALUE (1..n_trays); |
153 |
(* assemble into little pairs for building VLE states *) |
154 |
FOR k IN [Tray_set] CREATE |
155 |
trayVL[k][VLphases[k]] ALIASES |
156 |
(tray_vapor_mixture[k],tray_liquid_mixture[k]) |
157 |
WHERE VLphases[k] IS_A set OF symbol_constant |
158 |
WITH_VALUE ('vapor','liquid1'); |
159 |
END FOR; |
160 |
(* compile vle of each tray *) |
161 |
FOR k IN [1..n_trays] CREATE |
162 |
tray_state[k] IS_A |
163 |
thermodynamics(cd, pdVL, trayVL[k], equilibrated); |
164 |
END FOR; |
165 |
(* setup |
166 |
* tray_liqin[1..n_trays+1], tray_vapin[0..n_trays], |
167 |
* input streams. |
168 |
*) |
169 |
tray_vapin[tV] ALIASES (vapout.Details, |
170 |
internal_vapor_stream[2..n_trays], vapin.Details) |
171 |
WHERE tV IS_A set OF integer_constant |
172 |
WITH_VALUE (0..n_trays); |
173 |
|
174 |
tray_liqin[tL] ALIASES (liqin.Details, |
175 |
internal_liquid_stream[1..n_trays-1], liqout.Details) |
176 |
WHERE tL IS_A set OF integer_constant |
177 |
WITH_VALUE (1..n_trays+1); |
178 |
|
179 |
Qin[Tray_set] IS_A energy_rate; |
180 |
|
181 |
FOR k IN Tray_set CREATE |
182 |
Stack[k] IS_A detailed_tray( |
183 |
Qin[k], |
184 |
equilibrated, |
185 |
tray_liqin[k], |
186 |
tray_vapin[k], |
187 |
tray_liqin[k+1], |
188 |
tray_vapin[k-1], |
189 |
tray_state[k] |
190 |
); |
191 |
END FOR; |
192 |
|
193 |
FOR k IN Tray_set CREATE |
194 |
P[k] ALIASES tray_state[k].P; |
195 |
T[k] ALIASES tray_state[k].T; |
196 |
END FOR; |
197 |
|
198 |
METHODS |
199 |
|
200 |
METHOD default_all; |
201 |
RUN liqin.default_all; |
202 |
RUN liqout.default_all; |
203 |
RUN vapin.default_all; |
204 |
RUN vapout.default_all; |
205 |
RUN default_self; |
206 |
END default_all; |
207 |
|
208 |
METHOD default_self; |
209 |
Qin[Tray_set] := 0{watt}; |
210 |
boundwidth := 100; |
211 |
RUN pdVL.default_self; |
212 |
RUN internal_liquid_mixture[1..n_trays-1].default_self; |
213 |
RUN internal_vapor_mixture[2..n_trays].default_self; |
214 |
RUN internal_liquid_state[1..n_trays-1].default_self; |
215 |
RUN internal_vapor_state[2..n_trays].default_self; |
216 |
RUN internal_liquid_stream[1..n_trays-1].default_self; |
217 |
RUN internal_vapor_stream[2..n_trays].default_self; |
218 |
RUN tray_state[Tray_set].default_self; |
219 |
Stack[Tray_set].flowscale := 10{mole/second}; |
220 |
Stack[Tray_set].H_flowscale := 1000{J/second}; |
221 |
END default_self; |
222 |
|
223 |
METHOD check_all; |
224 |
RUN liqin.check_all; |
225 |
RUN liqout.check_all; |
226 |
RUN vapin.check_all; |
227 |
RUN vapout.check_all; |
228 |
RUN check_self; |
229 |
END check_all; |
230 |
|
231 |
METHOD check_self; |
232 |
RUN pdVL.check_self; |
233 |
RUN internal_liquid_mixture[1..n_trays-1].check_self; |
234 |
RUN internal_vapor_mixture[2..n_trays].check_self; |
235 |
RUN internal_liquid_state[1..n_trays-1].check_self; |
236 |
RUN internal_vapor_state[2..n_trays].check_self; |
237 |
RUN internal_liquid_stream[1..n_trays-1].check_self; |
238 |
RUN internal_vapor_stream[2..n_trays].check_self; |
239 |
RUN tray_state[Tray_set].check_self; |
240 |
END check_self; |
241 |
|
242 |
METHOD scale_all; |
243 |
RUN liqin.scale_all; |
244 |
RUN liqout.scale_all; |
245 |
RUN vapin.scale_all; |
246 |
RUN vapout.scale_all; |
247 |
RUN scale_self; |
248 |
END scale_all; |
249 |
|
250 |
METHOD scale_self; |
251 |
(* fortunately no local equations to scale *) |
252 |
RUN pdVL.scale_self; |
253 |
RUN internal_liquid_mixture[1..n_trays-1].scale_self; |
254 |
RUN internal_vapor_mixture[2..n_trays].scale_self; |
255 |
RUN internal_liquid_state[1..n_trays-1].scale_self; |
256 |
RUN internal_vapor_state[2..n_trays].scale_self; |
257 |
RUN internal_liquid_stream[1..n_trays-1].scale_self; |
258 |
RUN internal_vapor_stream[2..n_trays].scale_self; |
259 |
RUN tray_state[Tray_set].scale_self; |
260 |
END scale_self; |
261 |
|
262 |
METHOD bound_all; |
263 |
RUN liqin.bound_all; |
264 |
RUN liqout.bound_all; |
265 |
RUN vapin.bound_all; |
266 |
RUN vapout.bound_all; |
267 |
RUN bound_self; |
268 |
END bound_all; |
269 |
|
270 |
METHOD bound_self; |
271 |
(* fortunately no local variables to scale *) |
272 |
RUN pdVL.bound_self; |
273 |
|
274 |
internal_liquid_mixture[1..n_trays-1].boundwidth := boundwidth; |
275 |
internal_vapor_mixture[2..n_trays].boundwidth := boundwidth; |
276 |
internal_liquid_state[1..n_trays-1].boundwidth := boundwidth; |
277 |
internal_vapor_state[2..n_trays].boundwidth := boundwidth; |
278 |
internal_liquid_stream[1..n_trays-1].boundwidth := boundwidth; |
279 |
internal_vapor_stream[2..n_trays].boundwidth := boundwidth; |
280 |
tray_state[Tray_set].boundwidth := boundwidth; |
281 |
|
282 |
RUN internal_liquid_mixture[1..n_trays-1].bound_self; |
283 |
RUN internal_vapor_mixture[2..n_trays].bound_self; |
284 |
RUN internal_liquid_state[1..n_trays-1].bound_self; |
285 |
RUN internal_vapor_state[2..n_trays].bound_self; |
286 |
RUN internal_liquid_stream[1..n_trays-1].bound_self; |
287 |
RUN internal_vapor_stream[2..n_trays].bound_self; |
288 |
RUN tray_state[Tray_set].bound_self; |
289 |
|
290 |
END bound_self; |
291 |
|
292 |
METHOD specify; |
293 |
RUN seqmod; |
294 |
RUN liqin.specify; |
295 |
RUN vapin.specify; |
296 |
END specify; |
297 |
|
298 |
METHOD seqmod; |
299 |
RUN Stack[Tray_set].seqmod; |
300 |
END seqmod; |
301 |
|
302 |
METHOD scale; |
303 |
RUN Stack[Tray_set].scale; |
304 |
END scale; |
305 |
|
306 |
METHOD reset_to_mass_balance; |
307 |
equilibrated := FALSE; |
308 |
RUN reset; |
309 |
END reset_to_mass_balance; |
310 |
|
311 |
METHOD reset_to_full_thermo; |
312 |
equilibrated := TRUE; |
313 |
RUN reset; |
314 |
END reset_to_full_thermo; |
315 |
|
316 |
METHOD reset_to_adiabatic; |
317 |
RUN reset_to_full_thermo; |
318 |
Stack[Tray_set].cmo_ratio.fixed := FALSE; |
319 |
Stack[Tray_set].Qin.fixed := TRUE; |
320 |
Stack[Tray_set].Qin := 0{W}; |
321 |
END reset_to_adiabatic; |
322 |
|
323 |
METHOD reduce_Q; |
324 |
FOR j IN [Tray_set] DO |
325 |
Stack[j].Qin := reduce * Stack[j].Qin; |
326 |
END FOR; |
327 |
END reduce_Q; |
328 |
|
329 |
END tray_stack; |
330 |
|
331 |
MODEL test_tray_stack() REFINES testcmumodel(); |
332 |
n_trays_below IS_A integer_constant; |
333 |
n_trays_below :== 2; |
334 |
equilibrated IS_A start_false; |
335 |
reduce IS_A fraction; |
336 |
|
337 |
NOTES |
338 |
'usage' equilibrated { |
339 |
This variable and feed.equilibrated may or may not be the same. |
340 |
Do not assume they are when writing methods. |
341 |
} |
342 |
reduce { |
343 |
This is a fraction from 0 to 1. The method reduce_Q uses it |
344 |
to move the Qin on each stack and feed tray toward 0. |
345 |
Essentially this is a physical homotopy parameter. |
346 |
} |
347 |
END NOTES; |
348 |
|
349 |
|
350 |
cd IS_A components_data(['n_pentane','n_hexane','n_heptane'], |
351 |
'n_heptane'); |
352 |
pdV IS_A phases_data('V', 'Pitzer_vapor_mixture', 'none', 'none'); |
353 |
pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none'); |
354 |
|
355 |
Vapout IS_A stream(cd, pdV, equilibrated); |
356 |
Liqin IS_A stream(cd, pdL, equilibrated); |
357 |
Vapin IS_A stream(cd, pdV, equilibrated); |
358 |
Liqout IS_A stream(cd, pdL, equilibrated); |
359 |
|
360 |
Section IS_A tray_stack( |
361 |
n_trays_below, |
362 |
Vapout, |
363 |
Liqin, |
364 |
Vapin, |
365 |
Liqout, |
366 |
reduce, |
367 |
equilibrated |
368 |
); |
369 |
|
370 |
METHODS |
371 |
|
372 |
METHOD default_all; |
373 |
RUN default_self; |
374 |
END default_all; |
375 |
METHOD default_self; |
376 |
equilibrated := FALSE; |
377 |
RUN Section.default_self; |
378 |
END default_self; |
379 |
|
380 |
METHOD check_all; |
381 |
RUN check_self; |
382 |
END check_all; |
383 |
|
384 |
METHOD check_self; |
385 |
RUN Section.check_all; |
386 |
END check_self; |
387 |
|
388 |
METHOD bound_all; |
389 |
RUN bound_self; |
390 |
END bound_all; |
391 |
|
392 |
METHOD bound_self; |
393 |
RUN Section.bound_self; |
394 |
END bound_self; |
395 |
|
396 |
METHOD scale_all; |
397 |
RUN scale_self; |
398 |
END scale_all; |
399 |
|
400 |
METHOD scale_self; |
401 |
RUN Section.scale_self; |
402 |
END scale_self; |
403 |
|
404 |
METHOD specify; |
405 |
RUN Section.specify; |
406 |
END specify; |
407 |
|
408 |
METHOD reset_to_adiabatic; |
409 |
RUN Section.reset_to_adiabatic; |
410 |
END reset_to_adiabatic; |
411 |
END test_tray_stack; |
412 |
|
413 |
|
414 |
MODEL simple_column( |
415 |
pdVL WILL_BE phases_data; |
416 |
distillate WILL_BE stream; |
417 |
n_trays_above WILL_BE integer_constant; |
418 |
feed WILL_BE stream; |
419 |
n_trays_below WILL_BE integer_constant; |
420 |
bottoms WILL_BE stream; |
421 |
equilibrated WILL_BE boolean; |
422 |
reduce WILL_BE fraction; |
423 |
) WHERE ( |
424 |
n_trays_above > 1; |
425 |
n_trays_below > 1; |
426 |
distillate, bottoms, feed WILL_NOT_BE_THE_SAME; |
427 |
feed.cd, distillate.cd, bottoms.cd WILL_BE_THE_SAME; |
428 |
pdVL.phase_indicator == 'VL'; |
429 |
distillate.pd, bottoms.pd WILL_BE_THE_SAME; |
430 |
distillate.pd.phase_indicator == 'L'; |
431 |
pdVL.liquid1_option == distillate.pd.liquid1_option; |
432 |
feed.pd.phase_indicator IN ['V','L','VL'] == TRUE; |
433 |
) REFINES colmodel(); |
434 |
|
435 |
NOTES |
436 |
'ascii-picture' SELF { |
437 |
___ total condenser |
438 |
/ \________> distillate liquid |
439 |
|___| |
440 |
(condenser_vapin)^ | |
441 |
| | |
442 |
| v(rectifier_liqin) |
443 |
+---+ |
444 |
|___| |
445 |
|___| n_trays_above (at least 2) |
446 |
|___| |
447 |
|___| |
448 |
(rectifier_vapin)^ | |
449 |
| | |
450 |
| v(feed_tray_liqin) |
451 |
+---+ |
452 |
V/L feed ----->| | |
453 |
+___+ |
454 |
(feed_tray_vapin)^ | |
455 |
| | |
456 |
| v(stripper_liqin) |
457 |
+---+ |
458 |
|___| |
459 |
|___| n_trays_below (at least 2) |
460 |
|___| |
461 |
|___| |
462 |
(stripper_vapin)^ | |
463 |
| | |
464 |
| v(reboiler_liqin) |
465 |
___ |
466 |
| |________> bottoms liquid |
467 |
\___/ non-adiabatic flash |
468 |
} |
469 |
'usage' equilibrated { |
470 |
This variable and feed.equilibrated may or may not be the same. |
471 |
Do not assume they are when writing methods. |
472 |
} |
473 |
reduce { |
474 |
This is a fraction from 0 to 1. The method reduce_Q uses it |
475 |
to move the Qin on each stack and feed tray toward 0. |
476 |
Essentially this is a physical homotopy parameter. |
477 |
} |
478 |
'changing' SELF { |
479 |
This MODEL is very large, therefore it is very carefully |
480 |
structured following the ascii-picture. |
481 |
It should be relatively easy to modify this MODEL |
482 |
just by carefully following the patterns we use. The pattern is |
483 |
that all streams are given names corresponding to their input |
484 |
roles. |
485 |
|
486 |
You can build arbitrarily complicated columns with bypasses, |
487 |
recycles, intercoolers, etc just by copying this MODEL |
488 |
and rerouting section or tray connections after adding or |
489 |
removing sections, exchangers, and so forth. |
490 |
} |
491 |
END NOTES; |
492 |
|
493 |
(* |
494 |
* The creation steps: |
495 |
* alias the options from the feed stream. (done above). |
496 |
* inter-section streams (single phase) |
497 |
* column sections |
498 |
* At the end of the steps, everything has been wired up |
499 |
* simply by passing common parts to both places they belong. |
500 |
* For clarity, no arrays are used. |
501 |
* |
502 |
* If you are nuts enough to reimplement this MODEL using |
503 |
* arrays, have a look at tray_stack for techniques to avoid |
504 |
* sending the compiler to hell. |
505 |
* |
506 |
* The thermodynamic options of the given pdVL |
507 |
* column without using ARE_ALIKE or ARE_THE_SAME. |
508 |
*) |
509 |
|
510 |
pdL ALIASES bottoms.pd; |
511 |
pdV IS_A phases_data('V', pdVL.vapor_option, 'none', 'none'); |
512 |
cd ALIASES feed.cd; |
513 |
components ALIASES feed.components; |
514 |
|
515 |
(* inter-section streams *) |
516 |
condenser_vapin "vapor rising to condenser", |
517 |
rectifier_vapin "vapor rising from feed tray", |
518 |
feed_tray_vapin "vapor rising from stripper", |
519 |
stripper_vapin "vapor rising from reboiler" |
520 |
IS_A stream(cd, pdV, equilibrated); |
521 |
|
522 |
rectifier_liqin "reflux condensate", |
523 |
feed_tray_liqin "liquid falling from rectifier", |
524 |
stripper_liqin "liquid falling from feed tray", |
525 |
reboiler_liqin "liquid falling to reboiler" |
526 |
IS_A stream(cd, pdL, equilibrated); |
527 |
|
528 |
(* typical heat duties *) |
529 |
Qin_condenser "condenser duty", |
530 |
Qin_feed "feed heater duty", |
531 |
Qin_reboiler "reboiler duty" IS_A energy_rate; |
532 |
|
533 |
(* column sections *) |
534 |
condenser IS_A total_condenser( |
535 |
Qin_condenser, |
536 |
condenser_vapin, |
537 |
rectifier_liqin, |
538 |
distillate |
539 |
); |
540 |
rectifying_section "the trays above the feed" IS_A tray_stack( |
541 |
n_trays_above, |
542 |
condenser_vapin, |
543 |
rectifier_liqin, |
544 |
rectifier_vapin, |
545 |
feed_tray_liqin, |
546 |
reduce, |
547 |
equilibrated |
548 |
); |
549 |
feed_tray IS_A feed_tray( |
550 |
Qin_feed, |
551 |
equilibrated, |
552 |
feed, |
553 |
feed_tray_liqin, |
554 |
feed_tray_vapin, |
555 |
stripper_liqin, |
556 |
rectifier_vapin |
557 |
); |
558 |
stripping_section "the trays below the feed" IS_A tray_stack( |
559 |
n_trays_below, |
560 |
feed_tray_vapin, |
561 |
stripper_liqin, |
562 |
stripper_vapin, |
563 |
reboiler_liqin, |
564 |
reduce, |
565 |
equilibrated |
566 |
); |
567 |
reboiler IS_A simple_reboiler( |
568 |
Qin_reboiler, |
569 |
equilibrated, |
570 |
reboiler_liqin, |
571 |
stripper_vapin, |
572 |
bottoms |
573 |
); |
574 |
|
575 |
(* this array has the common type flash_base, |
576 |
* so it is mainly useful for methods. |
577 |
*) |
578 |
Tray[zTr] ALIASES ( |
579 |
condenser, |
580 |
rectifying_section.Stack[1..n_trays_above], |
581 |
feed_tray, |
582 |
stripping_section.Stack[1..n_trays_below], |
583 |
reboiler) |
584 |
WHERE zTr IS_A set OF integer_constant |
585 |
WITH_VALUE (0..N_trays); |
586 |
|
587 |
(* useful things to know from an END user perspective *) |
588 |
N_trays IS_A integer_constant; |
589 |
N_trays :== n_trays_above + 1 + n_trays_below + 1; |
590 |
VLE_set IS_A set OF integer_constant; |
591 |
VLE_set :== [1 .. N_trays]; |
592 |
Feed_loc IS_A integer_constant; |
593 |
Feed_loc :== n_trays_above +1; |
594 |
|
595 |
(* why is this here? total reflux? *) |
596 |
omb_slack[components] IS_A molar_rate; |
597 |
FOR i IN components CREATE |
598 |
overall_mass_balance[i]: |
599 |
feed.f[i] = (distillate.f[i] + bottoms.f[i] + omb_slack[i]); |
600 |
END FOR; |
601 |
|
602 |
METHODS |
603 |
|
604 |
METHOD default_self; |
605 |
omb_slack[components] := 0 {mol/s}; |
606 |
omb_slack[components].lower_bound := -1000{mole/s}; |
607 |
RUN condenser.default_self; |
608 |
RUN rectifying_section.default_self; |
609 |
RUN feed_tray.default_self; |
610 |
RUN stripping_section.default_self; |
611 |
RUN reboiler.default_self; |
612 |
END default_self; |
613 |
|
614 |
METHOD default_all; |
615 |
RUN pdVL.default_all; |
616 |
RUN distillate.default_all; |
617 |
RUN feed.default_all; |
618 |
RUN bottoms.default_all; |
619 |
RUN default_self; |
620 |
END default_all; |
621 |
|
622 |
METHOD check_all; |
623 |
RUN check_self; |
624 |
RUN pdVL.check_all; |
625 |
RUN distillate.check_all; |
626 |
RUN feed.check_all; |
627 |
RUN bottoms.check_all; |
628 |
END check_all; |
629 |
|
630 |
METHOD check_self; |
631 |
FOR i IN components DO |
632 |
IF ( omb_slack[i]/feed.flow.nominal > 1.0e-4 ) THEN |
633 |
STOP {Column violates over-all species balance}; |
634 |
END IF; |
635 |
END FOR; |
636 |
RUN pdV.check_self; |
637 |
RUN condenser_vapin.check_self; |
638 |
RUN rectifier_vapin.check_self; |
639 |
RUN feed_tray_vapin.check_self; |
640 |
RUN stripper_vapin.check_self; |
641 |
RUN rectifier_liqin.check_self; |
642 |
RUN feed_tray_liqin.check_self; |
643 |
RUN stripper_liqin.check_self; |
644 |
RUN reboiler_liqin.check_self; |
645 |
RUN condenser.check_self; |
646 |
RUN rectifying_section.check_self; |
647 |
RUN feed_tray.check_self; |
648 |
RUN stripping_section.check_self; |
649 |
RUN reboiler.check_self; |
650 |
END check_self; |
651 |
|
652 |
METHOD scale_all; |
653 |
RUN pdVL.scale_all; |
654 |
RUN distillate.scale_all; |
655 |
RUN feed.scale_all; |
656 |
RUN bottoms.scale_all; |
657 |
RUN scale_self; |
658 |
END scale_all; |
659 |
|
660 |
METHOD scale_self; |
661 |
RUN pdV.scale_self; |
662 |
RUN condenser_vapin.scale_self; |
663 |
RUN rectifier_vapin.scale_self; |
664 |
RUN feed_tray_vapin.scale_self; |
665 |
RUN stripper_vapin.scale_self; |
666 |
RUN rectifier_liqin.scale_self; |
667 |
RUN feed_tray_liqin.scale_self; |
668 |
RUN stripper_liqin.scale_self; |
669 |
RUN reboiler_liqin.scale_self; |
670 |
RUN condenser.scale_self; |
671 |
RUN rectifying_section.scale_self; |
672 |
RUN feed_tray.scale_self; |
673 |
RUN stripping_section.scale_self; |
674 |
RUN reboiler.scale_self; |
675 |
END scale_self; |
676 |
|
677 |
METHOD bound_all; |
678 |
RUN pdVL.bound_all; |
679 |
RUN distillate.bound_all; |
680 |
RUN feed.bound_all; |
681 |
RUN bottoms.bound_all; |
682 |
RUN bound_self; |
683 |
END bound_all; |
684 |
|
685 |
METHOD bound_self; |
686 |
RUN pdV.bound_self; |
687 |
RUN condenser_vapin.bound_self; |
688 |
RUN rectifier_vapin.bound_self; |
689 |
RUN feed_tray_vapin.bound_self; |
690 |
RUN stripper_vapin.bound_self; |
691 |
RUN rectifier_liqin.bound_self; |
692 |
RUN feed_tray_liqin.bound_self; |
693 |
RUN stripper_liqin.bound_self; |
694 |
RUN reboiler_liqin.bound_self; |
695 |
RUN condenser.bound_self; |
696 |
RUN rectifying_section.bound_self; |
697 |
RUN feed_tray.bound_self; |
698 |
RUN stripping_section.bound_self; |
699 |
RUN reboiler.bound_self; |
700 |
END bound_self; |
701 |
|
702 |
METHOD seqmod; |
703 |
RUN condenser.seqmod; |
704 |
RUN rectifying_section.seqmod; |
705 |
RUN feed_tray.seqmod; |
706 |
RUN stripping_section.seqmod; |
707 |
RUN reboiler.seqmod; |
708 |
END seqmod; |
709 |
|
710 |
METHOD specify; |
711 |
RUN seqmod; |
712 |
RUN feed.specify; |
713 |
IF (feed.equilibrated AND (feed.pd.phase_indicator == 'VL')) THEN |
714 |
feed.Details.state.phase[feed.pd.reference_phase].T.fixed := FALSE; |
715 |
feed.Details.state.phase_fraction[feed.pd.other_phases].fixed := TRUE; |
716 |
END IF; |
717 |
END specify; |
718 |
|
719 |
METHOD reset_to_mass_balance; |
720 |
equilibrated := FALSE; |
721 |
feed.state.equilibrated := FALSE; |
722 |
RUN reset; |
723 |
END reset_to_mass_balance; |
724 |
|
725 |
METHOD reset_to_full_thermo; |
726 |
equilibrated := TRUE; |
727 |
feed.state.equilibrated := TRUE; |
728 |
RUN reset; |
729 |
END reset_to_full_thermo; |
730 |
|
731 |
METHOD reset_to_adiabatic; |
732 |
RUN reset_to_full_thermo; |
733 |
(* condenser, reboiler Qin left free *) |
734 |
rectifying_section.Stack[1..n_trays_above].cmo_ratio.fixed := FALSE; |
735 |
stripping_section.Stack[1..n_trays_below].cmo_ratio.fixed := FALSE; |
736 |
Tray[1..N_trays-1].Qin.fixed := TRUE; |
737 |
Tray[1..N_trays-1].Qin := 0{W}; |
738 |
feed_tray.q.fixed := FALSE; |
739 |
END reset_to_adiabatic; |
740 |
|
741 |
METHOD propagate_feed_values; |
742 |
(* propagate feed tray flows and relative volatilities, |
743 |
* after solving the feed tray. |
744 |
*) |
745 |
FOR i IN components DO |
746 |
(* use feed alpha everywhere *) |
747 |
Tray[VLE_set].alpha[i] := feed_tray.alpha[i]; |
748 |
(* copy feed flow rates to all internal streams *) |
749 |
(* This copying should factor in the RR and BR *) |
750 |
Tray[0..N_trays-1].liqout.f[i] := feed.f[i]; |
751 |
Tray[1..N_trays].vapout.f[i] := feed.f[i]; |
752 |
END FOR; |
753 |
END propagate_feed_values; |
754 |
|
755 |
END simple_column; |
756 |
|
757 |
MODEL simple_column_profiles( |
758 |
sc WILL_BE simple_column; |
759 |
) REFINES colmodel(); |
760 |
|
761 |
traynum[sc.VLE_set] IS_A integer_constant; |
762 |
FOR i IN sc.VLE_set CREATE |
763 |
traynum[i] :== i; |
764 |
END FOR; |
765 |
|
766 |
cmo_ratio[zc] ALIASES ( |
767 |
sc.rectifying_section.Stack[1..sc.n_trays_above].cmo_ratio, |
768 |
sc.stripping_section.Stack[1..sc.n_trays_below].cmo_ratio) |
769 |
WHERE zc IS_A set OF integer_constant |
770 |
WITH_VALUE ( 1 .. sc.n_trays_above, |
771 |
sc.Feed_loc+1 .. sc.Feed_loc+sc.n_trays_below); |
772 |
|
773 |
P[zP] ALIASES ( |
774 |
sc.rectifying_section.P[1..sc.n_trays_above], |
775 |
sc.feed_tray.P, |
776 |
sc.stripping_section.P[1..sc.n_trays_below], |
777 |
sc.reboiler.P) |
778 |
WHERE zP IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
779 |
|
780 |
T[zT] ALIASES ( |
781 |
sc.rectifying_section.T[1..sc.n_trays_above], |
782 |
sc.feed_tray.T, |
783 |
sc.stripping_section.T[1..sc.n_trays_below], |
784 |
sc.reboiler.T) |
785 |
WHERE zT IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
786 |
|
787 |
(* next one is simple because flash_base defines Qin *) |
788 |
Qin[zQ] ALIASES (sc.Tray[0..sc.N_trays].Qin) |
789 |
WHERE zQ IS_A set OF integer_constant WITH_VALUE (0..sc.N_trays); |
790 |
|
791 |
Lin[zL] ALIASES ( |
792 |
sc.rectifying_section.tray_liqin[1..sc.n_trays_above].flow, |
793 |
sc.feed_tray.liqin.flow, |
794 |
sc.stripping_section.tray_liqin[1..sc.n_trays_below].flow, |
795 |
sc.reboiler.liqin.flow) |
796 |
WHERE zL IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
797 |
|
798 |
Vin[zV] ALIASES ( |
799 |
sc.rectifying_section.tray_vapin[0..sc.n_trays_above].flow, |
800 |
sc.feed_tray.vapin.flow, |
801 |
sc.stripping_section.tray_vapin[1..sc.n_trays_below].flow) |
802 |
WHERE zV IS_A set OF integer_constant WITH_VALUE (0..sc.N_trays-1); |
803 |
|
804 |
FOR i IN sc.components CREATE |
805 |
|
806 |
x[i][zx[i]] ALIASES ( |
807 |
sc.rectifying_section.Stack[1..sc.n_trays_above].x[i], |
808 |
sc.feed_tray.x[i], |
809 |
sc.stripping_section.Stack[1..sc.n_trays_below].x[i], |
810 |
sc.reboiler.x[i]) |
811 |
WHERE zx[i] IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
812 |
|
813 |
y[i][zy[i]] ALIASES ( |
814 |
sc.rectifying_section.Stack[1..sc.n_trays_above].y[i], |
815 |
sc.feed_tray.y[i], |
816 |
sc.stripping_section.Stack[1..sc.n_trays_below].y[i], |
817 |
sc.reboiler.y[i]) |
818 |
WHERE zy[i] IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
819 |
|
820 |
kvalues_when_full_thermo[i][zk[i]] ALIASES ( |
821 |
sc.rectifying_section.Stack[1..sc.n_trays_above].alpha[i], |
822 |
sc.feed_tray.alpha[i], |
823 |
sc.stripping_section.Stack[1..sc.n_trays_below].alpha[i], |
824 |
sc.reboiler.alpha[i]) |
825 |
WHERE zk[i] IS_A set OF integer_constant WITH_VALUE (sc.VLE_set); |
826 |
|
827 |
END FOR (* components *); |
828 |
|
829 |
METHODS |
830 |
(* This MODEL defines no new equations, variables, or submodels *) |
831 |
(* so we put in a bunch of harmless methods so the system defined |
832 |
* ones get replaced. |
833 |
*) |
834 |
METHOD check_self; |
835 |
END check_self; |
836 |
METHOD check_all; |
837 |
END check_all; |
838 |
METHOD default_self; |
839 |
END default_self; |
840 |
METHOD default_all; |
841 |
END default_all; |
842 |
METHOD scale_self; |
843 |
END scale_self; |
844 |
METHOD scale_all; |
845 |
END scale_all; |
846 |
METHOD bound_self; |
847 |
END bound_self; |
848 |
METHOD bound_all; |
849 |
END bound_all; |
850 |
METHOD specify; |
851 |
END specify; |
852 |
|
853 |
END simple_column_profiles; |
854 |
|
855 |
|
856 |
MODEL test_simple_column() REFINES testcmumodel(); |
857 |
|
858 |
cd IS_A components_data( |
859 |
['n_pentane','n_hexane','n_heptane'], 'n_heptane' |
860 |
); |
861 |
pdVL IS_A phases_data('VL','Pitzer_vapor_mixture', |
862 |
'UNIFAC_liquid_mixture','none'); |
863 |
pdV IS_A phases_data('V','Pitzer_vapor_mixture','none','none'); |
864 |
pdL IS_A phases_data('L','none','UNIFAC_liquid_mixture','none'); |
865 |
|
866 |
|
867 |
Feed_equil, Equilibrated IS_A start_false; |
868 |
Feed IS_A stream(cd, pdVL, Feed_equil); |
869 |
Distillate IS_A stream(cd, pdL, Equilibrated); |
870 |
Bottoms IS_A stream(cd, pdL, Equilibrated); |
871 |
|
872 |
n_trays_above, n_trays_below IS_A integer_constant; |
873 |
n_trays_above :== 6; |
874 |
n_trays_below :== 5; |
875 |
reduce IS_A fraction; |
876 |
Column IS_A simple_column( |
877 |
pdVL, |
878 |
Distillate, |
879 |
n_trays_above, |
880 |
Feed, |
881 |
n_trays_below, |
882 |
Bottoms, |
883 |
Equilibrated, |
884 |
reduce |
885 |
); |
886 |
|
887 |
Profile IS_A simple_column_profiles(Column); |
888 |
boundwidth IS_A bound_width; |
889 |
|
890 |
METHODS |
891 |
|
892 |
METHOD default_self; |
893 |
boundwidth := 100; |
894 |
RUN Feed.default_self; |
895 |
RUN Distillate.default_self; |
896 |
RUN Bottoms.default_self; |
897 |
RUN Column.default_self; |
898 |
RUN Profile.default_self; |
899 |
END default_self; |
900 |
|
901 |
METHOD check_self; |
902 |
RUN Feed.check_self; |
903 |
RUN Distillate.check_self; |
904 |
RUN Bottoms.check_self; |
905 |
RUN Column.check_self; |
906 |
RUN Profile.check_self; |
907 |
END check_self; |
908 |
|
909 |
METHOD scale_self; |
910 |
RUN Feed.scale_self; |
911 |
RUN Distillate.scale_self; |
912 |
RUN Bottoms.scale_self; |
913 |
RUN Column.scale_self; |
914 |
RUN Profile.scale_self; |
915 |
END scale_self; |
916 |
|
917 |
METHOD bound_self; |
918 |
Column.boundwidth := boundwidth; |
919 |
Profile.boundwidth := boundwidth; |
920 |
Feed.boundwidth := boundwidth; |
921 |
Distillate.boundwidth := boundwidth; |
922 |
Bottoms.boundwidth := boundwidth; |
923 |
RUN Feed.bound_self; |
924 |
RUN Distillate.bound_self; |
925 |
RUN Bottoms.bound_self; |
926 |
RUN Column.bound_self; |
927 |
RUN Profile.bound_self; |
928 |
END bound_self; |
929 |
|
930 |
METHOD bound_all; |
931 |
RUN bound_self; |
932 |
END bound_all; |
933 |
|
934 |
METHOD scale_all; |
935 |
RUN scale_self; |
936 |
END scale_all; |
937 |
|
938 |
METHOD check_all; |
939 |
RUN check_self; |
940 |
END check_all; |
941 |
|
942 |
METHOD default_all; |
943 |
RUN default_self; |
944 |
END default_all; |
945 |
|
946 |
METHOD values; |
947 |
Column.feed_tray.alpha['n_pentane'] := 3; |
948 |
Column.feed_tray.alpha['n_hexane'] := 2; |
949 |
Column.feed_tray.alpha['n_heptane'] := 1; |
950 |
Column.condenser.reflux_ratio := 1.3; |
951 |
Feed.T := 298 {K}; |
952 |
Feed.P := 1{atm}; |
953 |
Feed.f['n_pentane'] := 3{mole/s}; |
954 |
Feed.f['n_hexane'] := 3{mole/s}; |
955 |
Feed.f['n_heptane'] := 3{mole/s}; |
956 |
(* here we should SOLVE the feed tray *) |
957 |
RUN Column.propagate_feed_values; |
958 |
END values; |
959 |
|
960 |
END test_simple_column; |
961 |
|
962 |
MODEL demo_column( |
963 |
components IS_A set OF symbol_constant; |
964 |
reference IS_A symbol_constant; |
965 |
n_trays IS_A integer_constant; |
966 |
feed_location IS_A integer_constant; |
967 |
) WHERE ( |
968 |
reference IN components == TRUE; |
969 |
n_trays > 5; |
970 |
feed_location > 2; |
971 |
feed_location < n_trays - 2; |
972 |
) REFINES colmodel(); |
973 |
|
974 |
cd IS_A components_data(components,reference); |
975 |
pdVL IS_A phases_data('VL','Pitzer_vapor_mixture', |
976 |
'UNIFAC_liquid_mixture','none'); |
977 |
pdV IS_A phases_data('V','Pitzer_vapor_mixture','none','none'); |
978 |
pdL IS_A phases_data('L','none','UNIFAC_liquid_mixture','none'); |
979 |
|
980 |
Equilibrated IS_A start_false; |
981 |
Feed IS_A stream(cd, pdVL, Equilibrated); |
982 |
Distillate IS_A stream(cd, pdL, Equilibrated); |
983 |
Bottoms IS_A stream(cd, pdL, Equilibrated); |
984 |
|
985 |
n_trays_above, n_trays_below IS_A integer_constant; |
986 |
n_trays_above :== feed_location - 1; |
987 |
n_trays_below :== n_trays - feed_location - 1; |
988 |
reduce IS_A fraction; |
989 |
Column IS_A simple_column( |
990 |
pdVL, |
991 |
Distillate, |
992 |
n_trays_above, |
993 |
Feed, |
994 |
n_trays_below, |
995 |
Bottoms, |
996 |
Equilibrated, |
997 |
reduce |
998 |
); |
999 |
|
1000 |
(* component names in order of boiling point. useful for methods. *) |
1001 |
z_boiling_comp[1..CARD[components]] IS_A symbol; |
1002 |
z_bc IS_A symbol; |
1003 |
z_bi IS_A integer; |
1004 |
|
1005 |
METHODS |
1006 |
|
1007 |
METHOD default_self; |
1008 |
boundwidth := 100; |
1009 |
RUN Feed.default_self; |
1010 |
RUN Distillate.default_self; |
1011 |
RUN Bottoms.default_self; |
1012 |
RUN Column.default_self; |
1013 |
END default_self; |
1014 |
|
1015 |
METHOD check_self; |
1016 |
RUN Feed.check_self; |
1017 |
RUN Distillate.check_self; |
1018 |
RUN Bottoms.check_self; |
1019 |
RUN Column.check_self; |
1020 |
END check_self; |
1021 |
|
1022 |
METHOD scale_self; |
1023 |
RUN Feed.scale_self; |
1024 |
RUN Distillate.scale_self; |
1025 |
RUN Bottoms.scale_self; |
1026 |
RUN Column.scale_self; |
1027 |
END scale_self; |
1028 |
|
1029 |
METHOD bound_self; |
1030 |
Column.boundwidth := boundwidth; |
1031 |
Feed.boundwidth := boundwidth; |
1032 |
Distillate.boundwidth := boundwidth; |
1033 |
Bottoms.boundwidth := boundwidth; |
1034 |
RUN Feed.bound_self; |
1035 |
RUN Distillate.bound_self; |
1036 |
RUN Bottoms.bound_self; |
1037 |
RUN Column.bound_self; |
1038 |
END bound_self; |
1039 |
|
1040 |
METHOD bound_all; |
1041 |
RUN bound_self; |
1042 |
END bound_all; |
1043 |
|
1044 |
METHOD scale_all; |
1045 |
RUN scale_self; |
1046 |
END scale_all; |
1047 |
|
1048 |
METHOD check_all; |
1049 |
RUN check_self; |
1050 |
END check_all; |
1051 |
|
1052 |
METHOD default_all; |
1053 |
RUN default_self; |
1054 |
END default_all; |
1055 |
|
1056 |
METHOD values; |
1057 |
(* The demo user may very well want to rewrite this method |
1058 |
* for their particular mixture. |
1059 |
*) |
1060 |
z_bi := 1; |
1061 |
(* order the components arbitrarily in a list *) |
1062 |
FOR i IN components DO |
1063 |
z_boiling_comp[z_bi] := i; |
1064 |
z_bi := z_bi + 1; |
1065 |
END FOR; |
1066 |
(* use a bubble point sort, pun intended, to order the components. *) |
1067 |
FOR i IN [1..CARD[components]-1] DO |
1068 |
FOR j IN [i+1 .. CARD[components]] DO |
1069 |
IF cd.data[z_boiling_comp[i]].Tb > |
1070 |
cd.data[z_boiling_comp[j]].Tb THEN |
1071 |
z_bc := z_boiling_comp[j]; |
1072 |
z_boiling_comp[j] := z_boiling_comp[i]; |
1073 |
z_boiling_comp[i] := z_bc; |
1074 |
END IF; |
1075 |
END FOR; |
1076 |
END FOR; |
1077 |
z_bi := 1; |
1078 |
(* assign close alpha's *) |
1079 |
FOR i IN [1.. CARD[components]] DO |
1080 |
Column.feed_tray.alpha[z_boiling_comp[i]] := |
1081 |
1+ 1.0*(CARD[components]-i+1); (* 1.0 here --> 0.2 *) |
1082 |
IF (Feed.pd.phase_indicator == 'VL') THEN |
1083 |
Feed.state.phase['vapor'].alpha[z_boiling_comp[i]] := |
1084 |
Column.feed_tray.alpha[z_boiling_comp[i]]; |
1085 |
END IF; |
1086 |
END FOR; |
1087 |
Column.condenser.reflux_ratio := 1.3; |
1088 |
Feed.T := 298 {K}; |
1089 |
Feed.P := 1{atm}; |
1090 |
Feed.f[components] := 3{mole/s}; |
1091 |
RUN Column.propagate_feed_values; |
1092 |
END values; |
1093 |
|
1094 |
END demo_column; |
1095 |
|
1096 |
|
1097 |
MODEL test_demo_column() REFINES testcmumodel(); |
1098 |
|
1099 |
METHODS |
1100 |
METHOD check_self; |
1101 |
RUN demo.check_self; |
1102 |
END check_self; |
1103 |
METHOD check_all; |
1104 |
RUN demo.check_all; |
1105 |
END check_all; |
1106 |
METHOD default_self; |
1107 |
RUN demo.default_self; |
1108 |
END default_self; |
1109 |
METHOD default_all; |
1110 |
RUN demo.scale_all; |
1111 |
END default_all; |
1112 |
METHOD scale_self; |
1113 |
RUN demo.scale_self; |
1114 |
END scale_self; |
1115 |
METHOD scale_all; |
1116 |
RUN demo.scale_all; |
1117 |
END scale_all; |
1118 |
METHOD bound_self; |
1119 |
RUN demo.bound_self; |
1120 |
END bound_self; |
1121 |
METHOD bound_all; |
1122 |
RUN demo.bound_all; |
1123 |
END bound_all; |
1124 |
|
1125 |
METHOD specify; |
1126 |
RUN demo.specify; |
1127 |
END specify; |
1128 |
|
1129 |
METHOD values; |
1130 |
RUN demo.values; |
1131 |
END values; |
1132 |
|
1133 |
METHOD reset_to_mass_balance; |
1134 |
RUN demo.Column.reset_to_mass_balance; |
1135 |
END reset_to_mass_balance; |
1136 |
|
1137 |
METHOD reset_to_full_thermo; |
1138 |
RUN demo.Column.reset_to_full_thermo; |
1139 |
END reset_to_full_thermo; |
1140 |
|
1141 |
METHOD reset_to_adiabatic; |
1142 |
RUN demo.Column.reset_to_adiabatic; |
1143 |
END reset_to_adiabatic; |
1144 |
|
1145 |
END test_demo_column; |
1146 |
|
1147 |
MODEL mw_demo_column() REFINES test_demo_column(); |
1148 |
demo IS_A demo_column(['methanol','water'],'water',13,7); |
1149 |
METHODS |
1150 |
END mw_demo_column; |
1151 |
|
1152 |
MODEL abc_demo_column() REFINES test_demo_column(); |
1153 |
demo IS_A |
1154 |
demo_column(['benzene','chloroform','acetone'],'benzene',13,7); |
1155 |
METHODS |
1156 |
END abc_demo_column; |
1157 |
|
1158 |
MODEL c567_demo_column() REFINES test_demo_column(); |
1159 |
demo IS_A |
1160 |
demo_column(['n_pentane','n_hexane','n_heptane'],'n_heptane',13,7); |
1161 |
METHODS |
1162 |
END c567_demo_column; |