/[ascend]/trunk/models/ben/bencolumn.a4l
ViewVC logotype

Annotation of /trunk/models/ben/bencolumn.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 576 - (hide annotations) (download) (as text)
Tue May 9 03:42:08 2006 UTC (18 years, 2 months ago) by johnpye
File MIME type: text/x-ascend
File size: 25372 byte(s)
Changed all cases of *.fixed := {TRUE,FALSE} to 'FIX' and 'FREE' statements.
1 aw0a 1 REQUIRE "ben/benflash.a4l";
2     (* --> measures,system,atoms,components,options,HGthermo,stream,flash *)
3     PROVIDE "bencolumn.a4l";
4    
5     (*********************************************************************\
6     column.lib
7     by Ben Allan and Jennifer Perry
8     Part of the Ascend Library
9    
10     This file is part of the Ascend modeling library.
11     It defines basic tray-by-tray steady-state distillation models.
12    
13     Copyright (C) 1997 Carnegie Mellon University
14    
15     The Ascend modeling library is free software; you can redistribute
16     it and/or modify it under the terms of the GNU General Public License as
17     published by the Free Software Foundation; either version 2 of the
18     License, or (at your option) any later version.
19    
20     The Ascend Language Interpreter is distributed in hope that it will be
21     useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23     General Public License for more details.
24    
25     You should have received a copy of the GNU General Public License along with
26     the program; if not, write to the Free Software Foundation, Inc., 675
27     Mass Ave, Cambridge, MA 02139 USA. Check the file named COPYING.
28    
29     \*********************************************************************)
30    
31     (*********************************************************************\
32     $Date: 1998/06/01 15:43:22 $
33     $Revision: 1.1 $
34     $Author: ballan $
35     $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/ben/bencolumn.a4l,v $
36     \*********************************************************************)
37    
38     MODEL colmodel() REFINES cmumodel();
39     END colmodel;
40    
41     MODEL tray_stack(
42     n_trays WILL_BE integer_constant;
43     vapout WILL_BE vapor_stream;
44     liqin WILL_BE liquid_stream;
45     vapin WILL_BE vapor_stream;
46     liqout WILL_BE liquid_stream;
47     reduce WILL_BE fraction;
48     equilibrated WILL_BE boolean;
49     ) WHERE (
50     n_trays > 1;
51     vapout, liqin, vapin, liqout WILL_NOT_BE_THE_SAME;
52     vapout.state.options, vapin.state.options WILL_BE_THE_SAME;
53     liqout.state.options, liqin.state.options WILL_BE_THE_SAME;
54     ) REFINES colmodel();
55    
56     NOTES 'ascii-picture'
57     SELF {
58     vapout ^ |
59     | v liqin
60     +---+
61     |_1_|
62     |___| n_trays (at least 2)
63     |___|
64     |_n_|
65     vapin ^ |
66     | v liqout
67     }
68     'usage'
69     equilbrated {
70     When TRUE, enforces equilbrium between phases on all the trays.
71     When FALSE, uses constant alpha between phases on all the trays.
72     }
73     reduce {
74     Homotopy parameter used by reduce_Q to move fixed errors in the
75     energy balances (Qin per tray) toward 0.
76     }
77     END NOTES;
78    
79     liquid_options ALIASES liqout.state.options;
80     vapor_options ALIASES vapout.state.options;
81     internal_tray_P[2..n_trays-1] IS_A pressure;
82     internal_tray_T[2..n_trays-1] IS_A temperature;
83    
84     (*
85     * The ALIASES/IS_A break if the liqout,vapout are on the same tray.
86     *)
87     tray_P[tsP] ALIASES
88     (vapout.state.P, internal_tray_P[2..n_trays-1], liqout.state.P)
89     WHERE tsP IS_A set OF integer_constant
90     WITH_VALUE (1..n_trays);
91     tray_T[tsT] ALIASES
92     (vapout.state.T, internal_tray_T[2..n_trays-1], liqout.state.T)
93     WHERE tsT IS_A set OF integer_constant
94     WITH_VALUE (1..n_trays);
95    
96     FOR i IN [1..n_trays-1] CREATE
97     internal_liquid_state[i] IS_A liquid_mixture(
98     tray_P[i],
99     tray_T[i],
100     liquid_options
101     );
102     END FOR;
103     FOR i IN [2..n_trays] CREATE
104     internal_vapor_state[i] IS_A vapor_mixture(
105     tray_P[i],
106     tray_T[i],
107     vapor_options
108     );
109     END FOR;
110    
111     tray_liquid_state[tsL] ALIASES
112     (internal_liquid_state[1..n_trays-1], liqout.state)
113     WHERE tsL IS_A set OF integer_constant
114     WITH_VALUE (1..n_trays);
115     tray_vapor_state[tsV] ALIASES
116     (vapout.state,internal_vapor_state[2..n_trays])
117     WHERE tsV IS_A set OF integer_constant
118     WITH_VALUE (1..n_trays);
119    
120     FOR i IN [1..n_trays] CREATE
121     tray_state[i] IS_A td_VLE_mixture(
122     tray_P[i],
123     tray_T[i],
124     tray_vapor_state[i],
125     tray_liquid_state[i],
126     equilibrated
127     );
128     END FOR;
129     (* now like P,T, need to set up
130     * tray_liqin[1..n_trays+1], tray_vapin[0..n_trays],
131     * input streams.
132     *)
133     FOR i IN [2..n_trays] CREATE
134     internal_vapout[i] IS_A vapor_stream(
135     internal_vapor_state[i]
136     );
137     END FOR;
138     tray_vapin[tsIV] ALIASES
139     (vapout, internal_vapout[2..n_trays], vapin)
140     WHERE tsIV IS_A set OF integer_constant
141     WITH_VALUE (0..n_trays);
142    
143     FOR i IN [1..n_trays-1] CREATE
144     internal_liqout[i] IS_A liquid_stream(
145     internal_liquid_state[i]
146     );
147     END FOR;
148     tray_liqin[tsIL] ALIASES
149     (liqin, internal_liqout[1..n_trays-1], liqout)
150     WHERE tsIL IS_A set OF integer_constant
151     WITH_VALUE (1..n_trays+1);
152    
153     Tray_set IS_A set OF integer_constant;
154     (* TRUE but not necessary: Tray_set, tsL, tsV, tsP, tsT ARE_THE_SAME; *)
155     Tray_set :== tsL;
156    
157     FOR i IN Tray_set CREATE
158     Stack[i] IS_A tray(
159     tray_liqin[i],
160     tray_vapin[i],
161     tray_liqin[i+1],
162     tray_vapin[i-1],
163     tray_state[i]
164     );
165     END FOR;
166    
167     METHODS
168    
169     METHOD defaults;
170     RUN liqin.defaults;
171     RUN liqout.defaults;
172     RUN vapin.defaults;
173     RUN vapout.defaults;
174     RUN internal_liqout[1..n_trays-1].defaults;
175     RUN internal_vapout[2..n_trays].defaults;
176     Stack[Tray_set].F_scale := 10{mole/second};
177     Stack[Tray_set].H_scale := 1000{J/second};
178     END defaults;
179    
180     METHOD clear;
181     RUN Stack[Tray_set].clear;
182     END clear;
183    
184     METHOD specify;
185     RUN seqmod;
186     RUN liqin.specify;
187     RUN vapin.specify;
188     END specify;
189    
190     METHOD seqmod;
191     RUN Stack[Tray_set].seqmod;
192     END seqmod;
193    
194     METHOD reset;
195     RUN clear;
196     RUN specify;
197     END reset;
198    
199     METHOD scale;
200     RUN Stack[Tray_set].scale;
201     END scale;
202    
203     METHOD reset_to_massbal;
204     equilibrated := FALSE;
205     RUN reset;
206     END reset_to_massbal;
207    
208     METHOD reset_to_fullthermo;
209     equilibrated := TRUE;
210     RUN reset;
211     END reset_to_fullthermo;
212    
213     METHOD reset_to_adiabatic;
214     RUN reset_to_fullthermo;
215 johnpye 576 FREE Stack[Tray_set].cmo_ratio;
216     FIX Stack[Tray_set].Qin;
217 aw0a 1 Stack[Tray_set].Qin := 0{W};
218     END reset_to_adiabatic;
219    
220     METHOD reduce_Q;
221     FOR j IN [Tray_set] DO
222     Stack[j].Qin := reduce * Stack[j].Qin;
223     END FOR;
224     END reduce_Q;
225    
226     END tray_stack;
227    
228     MODEL test_tray_stack() REFINES testcmumodel();
229     n_trays_below IS_A integer_constant;
230     n_trays_below :== 2;
231     equilibrated IS_A boolean_start_false;
232     reduce IS_A fraction;
233    
234     NOTES
235     'usage' equilibrated {
236     This variable and feed.equilibrated may or may not be the same.
237     Do not assume they are when writing methods.
238     }
239     reduce {
240     This is a fraction from 0 to 1. The method reduce_Q uses it
241     to move the Qin on each stack and feed tray toward 0.
242     Essentially this is a physical homotopy parameter.
243     }
244     END NOTES;
245    
246     ds IS_A td_component_data_set(
247     ['n_pentane','n_hexane','n_heptane'],
248     'n_heptane'
249     );
250     vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
251     liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
252    
253     vapout_P, liqin_P, vapin_P, liqout_P IS_A pressure;
254    
255     vapout_T, liqin_T, vapin_T, liqout_T IS_A temperature;
256    
257     vapout_state IS_A vapor_mixture(vapout_P, vapout_T, vapor_options);
258     liqin_state IS_A liquid_mixture(liqin_P, liqin_T, liquid_options);
259     vapin_state IS_A vapor_mixture(vapin_P, vapin_T, vapor_options);
260     liqout_state IS_A liquid_mixture(liqout_P, liqout_T, liquid_options);
261    
262     Vapout IS_A vapor_stream(vapout_state);
263     Liqin IS_A liquid_stream(liqin_state);
264     Vapin IS_A vapor_stream(vapin_state);
265     Liqout IS_A liquid_stream(liqout_state);
266    
267     Section IS_A tray_stack(
268     n_trays_below,
269     Vapout,
270     Liqin,
271     Vapin,
272     Liqout,
273     reduce,
274     equilibrated
275     );
276    
277     METHODS
278    
279     METHOD defaults;
280     equilibrated := FALSE;
281     RUN Section.defaults;
282     END defaults;
283     METHOD reset;
284     RUN clear;
285     RUN specify;
286     END reset;
287    
288     METHOD clear;
289     RUN Section.clear;
290     END clear;
291    
292     METHOD specify;
293     RUN Section.specify;
294     END specify;
295    
296     METHOD reset_to_adiabatic;
297     RUN Section.reset_to_adiabatic;
298     END reset_to_adiabatic;
299    
300     METHOD scale;
301     RUN section.scale;
302     END scale;
303     END test_tray_stack;
304    
305     MODEL simple_column(
306     distillate WILL_BE liquid_stream;
307     n_trays_above WILL_BE integer_constant;
308     feed WILL_BE vapor_liquid_stream;
309     n_trays_below WILL_BE integer_constant;
310     bottoms WILL_BE liquid_stream;
311     equilibrated WILL_BE boolean;
312     reduce WILL_BE fraction;
313     ) WHERE (
314     n_trays_above > 1;
315     n_trays_below > 1;
316     distillate, bottoms, feed WILL_NOT_BE_THE_SAME;
317     bottoms.state.options, distillate.state.options,
318     feed.state.heavy.options WILL_BE_THE_SAME;
319     ) REFINES colmodel();
320    
321     liquid_options ALIASES feed.state.heavy.options;
322     vapor_options ALIASES feed.state.light.options;
323    
324     NOTES
325     'ascii-picture' SELF {
326     ___ total condenser
327     / \________> distillate liquid
328     |___|
329     (condensor_vapin)^ |
330     | |
331     | v(rectifier_liqin)
332     +---+
333     |___|
334     |___| n_trays_above (at least 2)
335     |___|
336     |___|
337     (rectifier_vapin)^ |
338     | |
339     | v(feed_tray_liqin)
340     +---+
341     V/L feed ----->| |
342     +___+
343     (feed_tray_vapin)^ |
344     | |
345     | v(stripper_liqin)
346     +---+
347     |___|
348     |___| n_trays_below (at least 2)
349     |___|
350     |___|
351     (stripper_vapin)^ |
352     | |
353     | v(reboiler_liqin)
354     ___
355     | |________> bottoms liquid
356     \___/ non-adiabatic flash
357     }
358     'usage' equilibrated {
359     This variable and feed.equilibrated may or may not be the same.
360     Do not assume they are when writing methods.
361     }
362     reduce {
363     This is a fraction from 0 to 1. The method reduce_Q uses it
364     to move the Qin on each stack and feed tray toward 0.
365     Essentially this is a physical homotopy parameter.
366     }
367     'changing' SELF {
368     This MODEL is very large, therefore it is very carefully
369     structured following the ascii-picture.
370     It should be relatively easy to modify this MODEL
371     just by carefully following the patterns we use. The pattern is
372     that all streams are given names corresponding to their input
373     roles and then all the subordinate P, T, state parts are named
374     by suffixing the corresponding stream names. When a part is
375     in common with the output streams, we create an internal name
376     following the regular pattern to keep the symmetries clear.
377     Note that the symmetries are preserved even in this aliasing.
378     }
379     END NOTES;
380    
381     (*
382     * The creation steps:
383     * alias the options from the feed stream. (done above).
384     * inter-section P,T, states (single phase)
385     * inter-section streams (single phase)
386     * reboiler and feed_tray states (two phase)
387     * column sections
388     * At the end of the steps, everything has been wired up
389     * simply by passing common parts to both places they belong.
390     * For clarity, no arrays are used.
391     *
392     * If you are nuts enough to reimplement this MODEL using
393     * arrays, have a look at tray_stack for techniques to avoid
394     * sending the compiler to hell.
395     *
396     * The thermodynamic options of the feed propagate to the whole
397     * column without using ARE_ALIKE or ARE_THE_SAME.
398     *)
399     (* thermodynamic P,T and state definitions for inter-section streams *)
400    
401     feed_tray_P IS_A pressure;
402     feed_tray_T IS_A temperature;
403    
404     condenser_vapin_P IS_A pressure;
405     rectifier_liqin_P ALIASES distillate.state.P;
406     rectifier_vapin_P ALIASES feed_tray_P;
407     feed_tray_liqin_P IS_A pressure;
408     feed_tray_vapin_P IS_A pressure;
409     stripper_liqin_P ALIASES feed_tray_P;
410     stripper_vapin_P ALIASES bottoms.state.P;
411     reboiler_liqin_P IS_A pressure;
412    
413     condenser_vapin_T IS_A temperature;
414     rectifier_liqin_T ALIASES distillate.state.T;
415     rectifier_vapin_T ALIASES feed_tray_T;
416     feed_tray_liqin_T IS_A temperature;
417     feed_tray_vapin_T IS_A temperature;
418     stripper_liqin_T ALIASES feed_tray_T;
419     stripper_vapin_T ALIASES bottoms.state.T;
420     reboiler_liqin_T IS_A temperature;
421    
422     condenser_vapin_state IS_A vapor_mixture(
423     condenser_vapin_P,
424     condenser_vapin_T,
425     vapor_options
426     );
427     rectifier_liqin_state ALIASES distillate.state;
428     rectifier_vapin_state IS_A vapor_mixture(
429     rectifier_vapin_P,
430     rectifier_vapin_T,
431     vapor_options
432     );
433     feed_tray_liqin_state IS_A liquid_mixture(
434     feed_tray_liqin_P,
435     feed_tray_liqin_T,
436     liquid_options
437     );
438     feed_tray_vapin_state IS_A vapor_mixture(
439     feed_tray_vapin_P,
440     feed_tray_vapin_T,
441     vapor_options
442     );
443     stripper_liqin_state IS_A liquid_mixture(
444     stripper_liqin_P,
445     stripper_liqin_T,
446     liquid_options
447     );
448     stripper_vapin_state IS_A vapor_mixture(
449     stripper_vapin_P,
450     stripper_vapin_T,
451     vapor_options
452     );
453     reboiler_liqin_state IS_A liquid_mixture(
454     reboiler_liqin_P,
455     reboiler_liqin_T,
456     liquid_options
457     );
458    
459     (* thermodynamic state definitions for reboiler, feed_tray *)
460     feed_tray_state IS_A td_VLE_mixture(
461     feed_tray_P,
462     feed_tray_T,
463     rectifier_vapin_state,
464     stripper_liqin_state,
465     equilibrated
466     );
467    
468     reboiler_state IS_A td_VLE_mixture(
469     stripper_vapin_P,
470     stripper_vapin_T,
471     stripper_vapin_state,
472     bottoms.state,
473     equilibrated
474     );
475    
476     (* inter-section streams *)
477     condenser_vapin IS_A vapor_stream(
478     condenser_vapin_state
479     );
480     rectifier_liqin IS_A liquid_stream(
481     rectifier_liqin_state
482     );
483     rectifier_vapin IS_A vapor_stream(
484     rectifier_vapin_state
485     );
486     feed_tray_liqin IS_A liquid_stream(
487     feed_tray_liqin_state
488     );
489     feed_tray_vapin IS_A vapor_stream(
490     feed_tray_vapin_state
491     );
492     stripper_liqin IS_A liquid_stream(
493     stripper_liqin_state
494     );
495     stripper_vapin IS_A vapor_stream(
496     stripper_vapin_state
497     );
498     reboiler_liqin IS_A liquid_stream(
499     reboiler_liqin_state
500     );
501    
502     (* column sections *)
503     condenser IS_A simple_condenser(
504     condenser_vapin,
505     rectifier_liqin,
506     distillate
507     );
508     rectifying_section IS_A tray_stack(
509     n_trays_above,
510     condenser_vapin,
511     rectifier_liqin,
512     rectifier_vapin,
513     feed_tray_liqin,
514     reduce,
515     equilibrated
516     );
517     feed_tray IS_A feed_tray(
518     feed,
519     feed_tray_liqin,
520     feed_tray_vapin,
521     stripper_liqin,
522     rectifier_vapin,
523     feed_tray_state
524     );
525     stripping_section IS_A tray_stack(
526     n_trays_below,
527     feed_tray_vapin,
528     stripper_liqin,
529     stripper_vapin,
530     reboiler_liqin,
531     reduce,
532     equilibrated
533     );
534     reboiler IS_A simple_reboiler(
535     reboiler_liqin,
536     stripper_vapin,
537     bottoms,
538     reboiler_state
539     );
540    
541     (* tray by tray profiles commonly desired *)
542     N_trays IS_A integer_constant;
543     N_trays :== n_trays_above + 1 + n_trays_below + 1;
544     VLE_set IS_A set OF integer_constant;
545     VLE_set :== [1 .. N_trays];
546     Feed_loc IS_A integer_constant;
547     Feed_loc :== n_trays_above +1;
548    
549     Tray[zTr] ALIASES (
550     condenser,
551     rectifying_section.Stack[1..n_trays_above],
552     feed_tray,
553     stripping_section.Stack[1..n_trays_below],
554     reboiler)
555     WHERE zTr IS_A set OF integer_constant
556     WITH_VALUE (0..N_trays);
557    
558     Profile_traynum[VLE_set] IS_A integer_constant;
559     FOR i IN VLE_set CREATE
560     Profile_traynum[i] :== i;
561     END FOR;
562    
563     Profile_P[zP] ALIASES (
564     rectifying_section.tray_P[1..n_trays_above],
565     feed_tray_P,
566     stripping_section.tray_P[1..n_trays_below],
567     bottoms.state.P)
568     WHERE zP IS_A set OF integer_constant WITH_VALUE (VLE_set);
569    
570     Profile_cmo_ratio[zc] ALIASES (
571     rectifying_section.Stack[1..n_trays_above].cmo_ratio,
572     stripping_section.Stack[1..n_trays_below].cmo_ratio)
573     WHERE zc IS_A set OF integer_constant
574     WITH_VALUE (1 .. n_trays_above, Feed_loc+1 .. Feed_loc+n_trays_below);
575    
576     Profile_T[zT] ALIASES (
577     rectifying_section.tray_T[1..n_trays_above],
578     feed_tray_T,
579     stripping_section.tray_T[1..n_trays_below],
580     bottoms.state.T)
581     WHERE zT IS_A set OF integer_constant WITH_VALUE (VLE_set);
582    
583     Profile_Qin[zQ] ALIASES (Tray[0..N_trays].Qin)
584     WHERE zQ IS_A set OF integer_constant WITH_VALUE (0..N_trays);
585    
586     Profile_Lin[zL] ALIASES (
587     rectifying_section.tray_liqin[1..n_trays_above].Ftot,
588     feed_tray.liqin.Ftot,
589     stripping_section.tray_liqin[1..n_trays_below].Ftot,
590     reboiler.liqin.Ftot)
591     WHERE zL IS_A set OF integer_constant WITH_VALUE (VLE_set);
592    
593     Profile_Vin[zV] ALIASES (
594     rectifying_section.tray_vapin[0..n_trays_above].Ftot,
595     feed_tray.vapin.Ftot,
596     stripping_section.tray_vapin[1..n_trays_below].Ftot)
597     WHERE zV IS_A set OF integer_constant WITH_VALUE (0..N_trays-1);
598    
599     components ALIASES feed.state.light.options.ds.components;
600     reference ALIASES feed.state.light.options.ds.reference;
601    
602     FOR i IN components CREATE
603    
604     Profile_x[i][zx[i]] ALIASES (
605     rectifying_section.Stack[1..n_trays_above].tray_state.heavy.y[i],
606     feed_tray_state.heavy.y[i],
607     stripping_section.Stack[1..n_trays_below].tray_state.heavy.y[i],
608     bottoms.state.y[i])
609     WHERE zx[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
610    
611     Profile_y[i][zy[i]] ALIASES (
612     rectifying_section.Stack[1..n_trays_above].tray_state.light.y[i],
613     feed_tray_state.light.y[i],
614     stripping_section.Stack[1..n_trays_below].tray_state.light.y[i],
615     reboiler_state.light.y[i])
616     WHERE zy[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
617    
618     Profile_kvalues_when_full_thermo[i][zk[i]] ALIASES (
619     rectifying_section.Stack[1..n_trays_above].tray_state.alpha[i],
620     feed_tray_state.alpha[i],
621     stripping_section.Stack[1..n_trays_below].tray_state.alpha[i],
622     reboiler_state.alpha[i])
623     WHERE zk[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
624    
625     END FOR;
626    
627     (*
628     VLE_set,
629     zx[components], zy[components], zk[components],
630     zT, zP ARE_THE_SAME; TRUE but not needed *)
631     (* zTr, zQ ARE_THE_SAME; TRUE but not needed *)
632    
633     omb_slack[components] IS_A molar_rate;
634     FOR i IN components CREATE
635     OMB[i]: feed.f[i] = (distillate.f[i] + bottoms.f[i] + omb_slack[i]);
636     END FOR;
637    
638     METHODS
639     METHOD defaults;
640     omb_slack[components] := 0{mol/s};
641     omb_slack[components].lower_bound := -1000{mole/s};
642     RUN condenser.defaults;
643     RUN rectifying_section.defaults;
644     RUN feed_tray.defaults;
645     RUN stripping_section.defaults;
646     RUN reboiler.defaults;
647     END defaults;
648    
649     METHOD clear;
650     RUN Tray[zTr].clear;
651 johnpye 576 FREE reduce;
652     FREE omb_slack[components];
653 aw0a 1 OMB[components].included:= TRUE;
654     END clear;
655    
656     METHOD overall_mb;
657     (* is this method still useful? *)
658     (* tray[Feed_loc].totfeedflow[components].included := FALSE; *)
659     omb_slack[components] := 0.0{mol/s};
660 johnpye 576 FIX omb_slack[components];
661 aw0a 1 END overall_mb;
662    
663     METHOD propagate_feed;
664     (* propagate feed tray flows and relative volatilities,
665     * presumably after solving the feed tray.
666     *)
667     FOR i IN components DO
668     rectifying_section.tray_state[1..n_trays_above].alpha[i] :=
669     feed_tray_state.alpha[i];
670     stripping_section.tray_state[1..n_trays_below].alpha[i] :=
671     feed_tray_state.alpha[i];
672     reboiler_state.alpha[i] := feed_tray_state.alpha[i];
673     (* copy feed flow rates to all internal streams *)
674     Tray[0..N_trays-1].liqout.f[i] := feed.f[i];
675     Tray[1..N_trays].vapout.f[i] := feed.f[i];
676     (* This copying should probably factor in the RR and BR *)
677     END FOR;
678     END propagate_feed;
679    
680     METHOD total_reflux;
681     (* this method is BROKEN in both this library and Bob's *)
682 johnpye 576 FIX condenser.reflux_ratio;
683 aw0a 1 condenser.reflux_def.included := FALSE;
684     (*
685     Tray[0].totprod.Ftot := 0.0{mol/s};
686 johnpye 576 FREE Tray[0].totprod.Ftot;
687 aw0a 1 *)
688 johnpye 576 FREE feed.f[components];
689 aw0a 1 feed_tray.qeq.included := FALSE;
690     feed.Ftot := 0.0{mol/s};
691 johnpye 576 FIX feed.Ftot;
692     feed_tray_state.y[components - [FIX reference]];
693     FIX feed_tray_state.phi['liquid'];
694 aw0a 1 feed_tray_state.phi['liquid'] := 0.5;
695     RUN feed_tray.liqout.specify;
696 johnpye 576 FIX reboiler.reboil_ratio;
697 aw0a 1 reboiler.reboil_def.included := FALSE;
698     END total_reflux;
699    
700     METHOD scale;
701     RUN condenser.scale;
702     RUN rectifying_section.scale;
703     RUN feed_tray.scale;
704     RUN stripping_section.scale;
705     RUN reboiler.scale;
706     END scale;
707    
708     METHOD seqmod;
709     RUN condenser.seqmod;
710     RUN rectifying_section.seqmod;
711     RUN feed_tray.seqmod;
712     RUN stripping_section.seqmod;
713     RUN reboiler.seqmod;
714     END seqmod;
715    
716     METHOD specify;
717     RUN seqmod;
718     RUN feed.specify;
719     END specify;
720    
721     METHOD reset;
722     RUN clear;
723     RUN specify;
724     END reset;
725    
726     METHOD reset_to_massbal;
727     equilibrated := FALSE;
728     feed.state.equilibrated := FALSE;
729     RUN reset;
730     END reset_to_massbal;
731    
732     METHOD reset_to_fullthermo;
733     equilibrated := TRUE;
734     feed.state.equilibrated := TRUE;
735     RUN reset;
736     END reset_to_fullthermo;
737    
738     METHOD reset_to_adiabatic;
739     RUN reset_to_fullthermo;
740     (* condenser, reboiler Qin left free *)
741 johnpye 576 FREE rectifying_section.Stack[1..n_trays_above].cmo_ratio;
742     FREE stripping_section.Stack[1..n_trays_below].cmo_ratio;
743     FIX Tray[1..N_trays-1].Qin;
744 aw0a 1 Tray[1..N_trays-1].Qin := 0{W};
745 johnpye 576 FREE feed_tray.q;
746 aw0a 1 END reset_to_adiabatic;
747    
748     END simple_column;
749    
750     MODEL test_simple_column() REFINES testcmumodel();
751    
752     ds IS_A td_component_data_set(
753     ['n_pentane','n_hexane','n_heptane'],
754     'n_heptane'
755     );
756     vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
757     liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
758    
759     feed_P IS_A pressure;
760     feed_T IS_A temperature;
761     feed_vapor_state IS_A vapor_mixture(
762     feed_P,
763     feed_T,
764     vapor_options
765     );
766     feed_liquid_state IS_A liquid_mixture(
767     feed_P,
768     feed_T,
769     liquid_options
770     );
771     Equilibrated IS_A boolean_start_false;
772     feed_state IS_A td_VLE_mixture(
773     feed_P,
774     feed_T,
775     feed_vapor_state,
776     feed_liquid_state,
777     Equilibrated
778     );
779     Feed IS_A vapor_liquid_stream(feed_state);
780    
781     distillate_P IS_A pressure;
782     distillate_T IS_A temperature;
783     distillate_state IS_A liquid_mixture(
784     distillate_P,
785     distillate_T,
786     liquid_options
787     );
788     Distillate IS_A liquid_stream(distillate_state);
789    
790     bottoms_P IS_A pressure;
791     bottoms_T IS_A temperature;
792     bottoms_state IS_A liquid_mixture(
793     bottoms_P,
794     bottoms_T,
795     liquid_options
796     );
797     Bottoms IS_A liquid_stream(bottoms_state);
798    
799     n_trays_above, n_trays_below IS_A integer_constant;
800     n_trays_above :== 6;
801     n_trays_below :== 5;
802     reduce IS_A fraction;
803     Column IS_A simple_column(
804     Distillate,
805     n_trays_above,
806     Feed,
807     n_trays_below,
808     Bottoms,
809     Equilibrated,
810     reduce
811     );
812    
813     METHODS
814     METHOD defaults;
815     RUN Column.defaults;
816     END defaults;
817     METHOD clear;
818     RUN Feed.clear;
819     RUN Column.clear;
820     Equilibrated := TRUE;
821     END clear;
822    
823     METHOD values;
824     Column.feed_tray_state.alpha['n_pentane'] := 3;
825     Column.feed_tray_state.alpha['n_hexane'] := 2;
826     Column.feed_tray_state.alpha['n_heptane'] := 1;
827     Column.condenser.reflux_ratio := 1.3;
828     feed_T := 298 {K};
829     feed_P := 1{atm};
830     Feed.f['n_pentane'] := 3{mole/s};
831     Feed.f['n_hexane'] := 3{mole/s};
832     Feed.f['n_heptane'] := 3{mole/s};
833     (* here we should SOLVE the feed tray *)
834     RUN Column.propagate_feed;
835     END values;
836    
837     METHOD scale;
838     RUN Column.scale;
839     END scale;
840     END test_simple_column;
841    
842     MODEL demo_column(
843     components IS_A set OF symbol_constant;
844     reference IS_A symbol_constant;
845     n_trays IS_A integer_constant;
846     feed_location IS_A integer_constant;
847     ) WHERE (
848     reference IN components == TRUE;
849     n_trays > 5;
850     feed_location > 2;
851     feed_location < n_trays - 2;
852     ) REFINES colmodel();
853    
854     ds IS_A td_component_data_set(components,reference);
855     vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
856     liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
857    
858     feed_P IS_A pressure;
859     feed_T IS_A temperature;
860     feed_vapor_state IS_A vapor_mixture(
861     feed_P,
862     feed_T,
863     vapor_options
864     );
865     feed_liquid_state IS_A liquid_mixture(
866     feed_P,
867     feed_T,
868     liquid_options
869     );
870     Equilibrated IS_A boolean_start_true;
871     feed_state IS_A td_VLE_mixture(
872     feed_P,
873     feed_T,
874     feed_vapor_state,
875     feed_liquid_state,
876     Equilibrated
877     );
878     Feed IS_A vapor_liquid_stream(feed_state);
879    
880     distillate_P IS_A pressure;
881     distillate_T IS_A temperature;
882     distillate_state IS_A liquid_mixture(
883     distillate_P,
884     distillate_T,
885     liquid_options
886     );
887     Distillate IS_A liquid_stream(distillate_state);
888    
889     bottoms_P IS_A pressure;
890     bottoms_T IS_A temperature;
891     bottoms_state IS_A liquid_mixture(
892     bottoms_P,
893     bottoms_T,
894     liquid_options
895     );
896     Bottoms IS_A liquid_stream(bottoms_state);
897    
898     n_trays_above, n_trays_below IS_A integer_constant;
899     n_trays_above :== feed_location - 1;
900     n_trays_below :== n_trays - feed_location - 1;
901     reduce IS_A fraction;
902     Column IS_A simple_column(
903     Distillate,
904     n_trays_above,
905     Feed,
906     n_trays_below,
907     Bottoms,
908     Equilibrated,
909     reduce
910     );
911    
912     (* component names in order of boiling point. useful for methods. *)
913     z_boiling_comp[1..CARD[components]] IS_A symbol;
914     z_bc IS_A symbol;
915     z_bi IS_A integer;
916     METHODS
917     METHOD defaults;
918     RUN Column.defaults;
919     END defaults;
920     METHOD clear;
921     RUN Feed.clear;
922     RUN Column.clear;
923     Equilibrated := TRUE;
924     END clear;
925    
926     METHOD values;
927     (* The demo user may very well want to rewrite this method
928     * for their particular mixture.
929     *)
930     z_bi := 1;
931     (* order the components arbitrarily in a list *)
932     FOR i IN components DO
933     z_boiling_comp[z_bi] := i;
934     z_bi := z_bi + 1;
935     END FOR;
936     (* use a bubble point sort, pun intended, to order the components. *)
937     FOR i IN [1..CARD[components]-1] DO
938     FOR j IN [i+1 .. CARD[components]] DO
939     IF ds.data[z_boiling_comp[i]].Tb >
940     ds.data[z_boiling_comp[j]].Tb THEN
941     z_bc := z_boiling_comp[j];
942     z_boiling_comp[j] := z_boiling_comp[i];
943     z_boiling_comp[i] := z_bc;
944     END IF;
945     END FOR;
946     END FOR;
947     z_bi := 1;
948     (* assign integer alpha's *)
949     FOR i IN [1.. CARD[components]] DO
950     Column.feed_tray_state.alpha[z_boiling_comp[i]] :=
951     CARD[components]-i+1;
952     END FOR;
953     Column.condenser.reflux_ratio := 1.3;
954     feed_T := 298 {K};
955     feed_P := 1{atm};
956     Feed.f[components] := 3{mole/s};
957     RUN Column.propagate_feed;
958     END values;
959    
960     METHOD scale;
961     RUN Column.scale;
962     END scale;
963     END demo_column;
964    
965     MODEL test_demo_column() REFINES testcmumodel();
966     END test_demo_column;
967    
968     MODEL mw_demo_column() REFINES test_demo_column();
969     mw_column IS_A demo_column(['methanol','water'],'water',13,7);
970     METHODS
971     METHOD defaults;
972     RUN mw_column.defaults;
973     END defaults;
974     END mw_demo_column;
975    
976     MODEL abc_demo_column() REFINES test_demo_column();
977     abc_column IS_A
978     demo_column(['benzene','chloroform','acetone'],'benzene',13,7);
979     METHODS
980     METHOD defaults;
981     RUN abc_column.defaults;
982     END defaults;
983     END abc_demo_column;
984    
985     MODEL c567_demo_column() REFINES test_demo_column();
986     c567_column IS_A
987     demo_column(['n_pentane','n_hexane','n_heptane'],'n_heptane',13,7);
988     METHODS
989     METHOD defaults;
990     RUN c567_column.defaults;
991     END defaults;
992     END c567_demo_column;

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