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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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