/[ascend]/trunk/models/simpleflowsheet02.a4c
ViewVC logotype

Contents of /trunk/models/simpleflowsheet02.a4c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 576 - (show annotations) (download) (as text)
Tue May 9 03:42:08 2006 UTC (13 years, 7 months ago) by johnpye
File MIME type: text/x-ascend
File size: 13016 byte(s)
Changed all cases of *.fixed := {TRUE,FALSE} to 'FIX' and 'FREE' statements.
1 REQUIRE "atoms.a4l";
2 (* => atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *)
3 PROVIDE "simpleflowsheet02.a4c";
4
5 (*
6 * simpleflowsheet02.a4c
7 * by Arthur W. Westerberg
8 * Part of the ASCEND Library
9 * $Date: 2006/04/10 10:08:42 $
10 * $Revision: 1.95 $
11 * $Author: a.westerberg $
12 *
13 * This file is part of the ASCEND Modeling Library.
14 *
15 * Copyright (C) 1998 Carnegie Mellon University
16 *
17 * The ASCEND Modeling Library is free software; you can redistribute
18 * it and/or modify it under the terms of the GNU General Public
19 * License as published by the Free Software Foundation; either
20 * version 2 of the License, or (at your option) any later version.
21 *
22 * The ASCEND Modeling Library is distributed in hope that it
23 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
24 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 * See the GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with the program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check
30 * the file named COPYING.
31 *)
32
33
34 (*
35
36 This file contains code to model the same flowsheet as
37
38 simpleflowsheet01.a4c
39
40 EXCEPT we have modified most of the models to be parameterized. We
41 strongly recommend creating parameterized models as they tend to be
42 much easier to reuse. The model simpleflowsheet01.a4c uses a modeling
43 style based on ARE_THE_SAME statements to configure the flowsheet, a
44 style that can often be easier to write initially. However, reuse is
45 not its strength.
46
47 We have included this model to aid new ASCEND users to understand
48 better how to write parameterized models.
49
50 ------------------------------------------------------------------
51
52 The following example illustrates equation based modeling using the
53 ASCEND system. The process is a simple recycle process.
54
55
56
57 -------
58 | |
59 ----------------------| split |----> purge
60 | | |
61 | -------
62 | ^
63 v |
64 ----- --------- -------
65 | | | | | |
66 ----->| mix |--->| reactor |--->| flash |
67 | | | | | |
68 ----- --------- -------
69 |
70 |
71 -----> C
72
73 This model requires: "system.a4l"
74 "atoms.a4l"
75 *)
76
77
78 (* ************************************************* *)
79
80
81 MODEL mixture(
82 components WILL_BE set OF symbol_constant;
83 );
84
85 (* Note: we now pass the set components into this model *)
86
87 y[components] IS_A fraction;
88 sumy: SUM[y[i] | i IN components] = 1.0;
89
90 METHODS
91
92 METHOD default_self;
93 END default_self;
94
95 METHOD specify;
96 FIX y[components];
97 FREE y[CHOICE[components]];
98 END specify;
99
100 METHOD reset;
101 RUN ClearAll;
102 RUN specify;
103 END reset;
104
105 END mixture;
106
107 (* ************************************************* *)
108
109
110 MODEL molar_stream(
111 components WILL_BE set OF symbol_constant;
112 );
113
114 (* Note: we now pass the set components into this model *)
115
116 state IS_A mixture(components);
117
118 (* and we pass it on into the defining of state. In this
119 manner we assure that the same set is used in both places
120 when defining the model. We had to use ARE_THE_SAME in
121 the earlier model to guarantee both used the same
122 components set.
123 *)
124
125 Ftot,f[components] IS_A molar_rate;
126
127 FOR i IN components CREATE
128 f_def[i]: f[i] = Ftot*state.y[i];
129 END FOR;
130
131 METHODS
132
133 METHOD default_self;
134 END default_self;
135
136 METHOD seqmod;
137 RUN state.specify;
138 FREE state.y[components];
139 END seqmod;
140
141 METHOD specify;
142 RUN seqmod;
143 FIX f[components];
144 END specify;
145
146 METHOD reset;
147 RUN ClearAll;
148 RUN specify;
149 END reset;
150
151 METHOD scale;
152 FOR i IN components DO
153 f[i].nominal := f[i] + 0.1{mol/s};
154 END FOR;
155 Ftot.nominal := Ftot + 0.1{mol/s};
156 END scale;
157
158 END molar_stream;
159
160 (* ************************************************* *)
161
162
163 MODEL mixer(
164 n_inputs WILL_BE integer_constant;
165 feed[1..n_inputs] WILL_BE molar_stream;
166 out WILL_BE molar_stream;
167 );
168
169 (* We pass all the streams into this model definition.
170 as opposed to defining them within this model.
171 *)
172
173
174 FOR i IN out.components CREATE
175 cmb[i]: out.f[i] = SUM[feed[1..n_inputs].f[i]];
176 END FOR;
177
178 METHODS
179
180 METHOD default_self;
181 END default_self;
182
183 METHOD seqmod;
184 END seqmod;
185
186 METHOD specify;
187 RUN seqmod;
188 RUN feed[1..n_inputs].specify;
189 END specify;
190
191 METHOD reset;
192 RUN ClearAll;
193 RUN specify;
194 END reset;
195
196 METHOD scale;
197 RUN feed[1..n_inputs].scale;
198 RUN out.scale;
199 END scale;
200
201 END mixer;
202
203 (* ************************************************* *)
204
205
206 MODEL reactor(
207 feed WILL_BE molar_stream;
208 out WILL_BE molar_stream;
209 );
210
211 turnover IS_A molar_rate;
212 stoich_coef[feed.components] IS_A factor;
213
214 FOR i IN feed.components CREATE
215 cmb[i]: out.f[i] = feed.f[i] + stoich_coef[i]*turnover;
216 END FOR;
217
218 METHODS
219
220 METHOD default_self;
221 END default_self;
222
223 METHOD seqmod;
224 FIX turnover;
225 FIX stoich_coef[feed.components];
226 END seqmod;
227
228 METHOD specify;
229 RUN seqmod;
230 RUN feed.specify;
231 END specify;
232
233 METHOD reset;
234 RUN ClearAll;
235 RUN specify;
236 END reset;
237
238 METHOD scale;
239 RUN feed.scale;
240 RUN out.scale;
241 turnover.nominal := turnover.nominal+0.0001 {kg_mole/s};
242 END scale;
243
244 END reactor;
245
246 (* ************************************************* *)
247
248
249 MODEL flash(
250 feed WILL_BE molar_stream;
251 vap WILL_BE molar_stream;
252 liq WILL_BE molar_stream;
253 );
254
255 alpha[feed.components],
256 ave_alpha IS_A factor;
257 vap_to_feed_ratio IS_A fraction;
258
259 VFratio: vap_to_feed_ratio*feed.Ftot = vap.Ftot;
260
261 FOR i IN feed.components CREATE
262 cmb[i]: feed.f[i] = vap.f[i] + liq.f[i];
263 eq[i]: vap.state.y[i]*ave_alpha = alpha[i]*liq.state.y[i];
264 END FOR;
265
266 METHODS
267
268 METHOD default_self;
269 END default_self;
270
271 METHOD seqmod;
272 FIX alpha[feed.components];
273 FIX vap_to_feed_ratio;
274 END seqmod;
275
276 METHOD specify;
277 RUN seqmod;
278 RUN feed.specify;
279 END specify;
280
281 METHOD reset;
282 RUN ClearAll;
283 RUN specify;
284 END reset;
285
286 METHOD scale;
287 RUN feed.scale;
288 RUN vap.scale;
289 RUN liq.scale;
290 END scale;
291
292 END flash;
293
294 (* ************************************************* *)
295
296
297 MODEL splitter(
298 n_outputs WILL_BE integer_constant;
299 feed WILL_BE molar_stream;
300 out[1..n_outputs] WILL_BE molar_stream;
301 );
302
303 split[1..n_outputs] IS_A fraction;
304
305 compsLessOne IS_A set OF symbol_constant;
306 compsLessOne :== feed.components - [CHOICE[feed.components]];
307
308 FOR j IN [1..n_outputs] CREATE
309 FOR i IN compsLessOne CREATE
310 splitState[j][i]: out[j].state.y[i] = feed.state.y[i];
311 END FOR;
312 cmb[j]: out[j].Ftot = split[j]*feed.Ftot;
313 END FOR;
314
315 sumSplits: SUM[split[1..n_outputs]] = 1.0;
316
317 METHODS
318
319 METHOD default_self;
320 END default_self;
321
322 METHOD seqmod;
323 FIX split[1..n_outputs-1];
324 END seqmod;
325
326 METHOD specify;
327 RUN seqmod;
328 RUN feed.specify;
329 END specify;
330
331 METHOD reset;
332 RUN ClearAll;
333 RUN specify;
334 END reset;
335
336 METHOD scale;
337 RUN feed.scale;
338 RUN out[1..n_outputs].scale;
339 END scale;
340
341 END splitter;
342
343 (* ************************************************* *)
344
345
346 MODEL flowsheet;
347
348 (*
349
350 It is in this model that the largest changes occur to create
351 parameterized models. We now define the set named components and all
352 the streams in this model and pass those definitions into the model
353 parts that require them. We do not and need not use any ARE_THE_SAME
354 statements.
355
356 Note in particular the use of the ALIASES statements below to allow
357 the two feeds to the mixer and the two output streams from the
358 splitter to be given array names as aliases. The mixer unit expects
359 to receive an array of n_inputs input streams. The splitter expects
360 an array of output streams. One of the inputs to the mixer is also
361 one of the outputs from the splitter. An array element such as a[1]
362 is simply the name for that element, to distinguish it from a[2].
363 Such naming does not imply contiguous storage.
364
365 *)
366
367
368
369 (* define sets *)
370
371 components IS_A set OF symbol_constant;
372 n_inputs, n_outputs IS_A integer_constant;
373 n_inputs :== 2;
374 n_outputs :== 2;
375
376 (* define streams *)
377
378 fsFeed,
379 recycle,
380 mixOut,
381 reactOut,
382 liqOut,
383 vapOut,
384 bleed IS_A molar_stream(components);
385
386 mixFeed[mixInputs] ALIASES (fsFeed,recycle)
387 WHERE mixInputs IS_A set OF integer_constant
388 WITH_VALUE (1..n_inputs);
389
390 splitOut[splitOutputs] ALIASES (bleed,recycle)
391 WHERE splitOutputs IS_A set OF integer_constant
392 WITH_VALUE (1..n_outputs);
393
394 (* define and wireup flowsheet *)
395 m1 IS_A mixer(n_inputs,mixFeed,mixOut);
396 r1 IS_A reactor(mixOut, reactOut);
397 fl1 IS_A flash(reactOut, vapOut, liqOut);
398 sp1 IS_A splitter(n_outputs, vapOut, splitOut);
399
400 METHODS
401
402 METHOD default_self;
403 END default_self;
404
405 METHOD seqmod;
406 RUN m1.seqmod;
407 RUN r1.seqmod;
408 RUN fl1.seqmod;
409 RUN sp1.seqmod;
410 END seqmod;
411
412 METHOD specify;
413 RUN seqmod;
414 RUN m1.feed[1].specify;
415 END specify;
416
417 METHOD reset;
418 RUN ClearAll;
419 RUN specify;
420 END reset;
421
422 METHOD scale;
423 RUN m1.scale;
424 RUN r1.scale;
425 RUN fl1.scale;
426 RUN sp1.scale;
427 END scale;
428
429 END flowsheet;
430
431 (* ************************************************* *)
432
433
434 MODEL controller;
435
436 fs IS_A flowsheet;
437 conv IS_A fraction;
438 key_components IS_A symbol_constant;
439
440 convControl: fs.r1.out.f[key_components] =
441 (1 - conv)*fs.r1.feed.f[key_components];
442
443 METHODS
444
445 METHOD default_self;
446 END default_self;
447
448 METHOD specify;
449 RUN fs.specify;
450 FREE fs.r1.turnover;
451 FIX conv;
452 END specify;
453
454 METHOD reset;
455 RUN ClearAll;
456 RUN specify;
457 END reset;
458
459 METHOD scale;
460 RUN fs.scale;
461 END scale;
462
463 END controller;
464
465 (* ************************************************* *)
466
467
468 MODEL test_flowsheet REFINES flowsheet;
469
470 components :== ['A','B','C'];
471
472 METHODS
473
474 METHOD default_self;
475 (* no-op. here to avoid STOP statement. *)
476 END default_self;
477
478 METHOD values;
479 m1.feed[1].f['A'] := 0.005 {kg_mole/s};
480 m1.feed[1].f['B'] := 0.095 {kg_mole/s};
481 m1.feed[1].f['C'] := 0.0 {kg_mole/s};
482
483 r1.stoich_coef['A'] := 0;
484 r1.stoich_coef['B'] := -1;
485 r1.stoich_coef['C'] := 1;
486
487 fl1.alpha['A'] := 12.0;
488 fl1.alpha['B'] := 10.0;
489 fl1.alpha['C'] := 1.0;
490 fl1.vap_to_feed_ratio := 0.9;
491 fl1.ave_alpha := 5.0;
492
493 sp1.split[1] := 0.01;
494
495 fl1.liq.Ftot := m1.feed[1].f['B'];
496 END values;
497
498 END test_flowsheet;
499
500 (* ************************************************* *)
501
502
503 MODEL test_controller REFINES controller;
504
505 fs IS_REFINED_TO test_flowsheet;
506 key_components :== 'B';
507
508 METHODS
509
510 METHOD default_self;
511 (* no-op. here to avoid STOP statement. *)
512 END default_self;
513
514 METHOD values;
515 RUN fs.values;
516 conv := 0.07;
517 END values;
518
519 END test_controller;

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