1 |
REQUIRE "atoms.a4l"; |
2 |
(* => atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *) |
3 |
PROVIDE "simple_fs.a4c"; |
4 |
(* |
5 |
* This file is part of the ASCEND Modeling Library and is released |
6 |
* under the GNU Public License as described at the end of this file. |
7 |
* |
8 |
* Use of this module is demonstrated by the associated script file |
9 |
* simple_fs.a4s. |
10 |
*) |
11 |
|
12 |
(* |
13 |
|
14 |
The following example illustrates equation based modeling using the |
15 |
ASCEND system. The process is a simple recycle process. |
16 |
|
17 |
|
18 |
|
19 |
------- |
20 |
| | |
21 |
----------------------| split |----> purge |
22 |
| | | |
23 |
| ------- |
24 |
| ^ |
25 |
v | |
26 |
----- --------- ------- |
27 |
| | | | | | |
28 |
----->| mix |--->| reactor |--->| flash | |
29 |
| | | | | | |
30 |
----- --------- ------- |
31 |
| |
32 |
| |
33 |
-----> C |
34 |
|
35 |
This model requires: "system.a4l" |
36 |
"atoms.a4l" |
37 |
*) |
38 |
|
39 |
|
40 |
(* ************************************************* *) |
41 |
|
42 |
|
43 |
MODEL mixture; |
44 |
|
45 |
components IS_A set OF symbol_constant; |
46 |
y[components] IS_A fraction; |
47 |
|
48 |
SUM[y[i] | i IN components] = 1.0; |
49 |
|
50 |
METHODS |
51 |
|
52 |
METHOD clear; |
53 |
y[components].fixed := FALSE; |
54 |
END clear; |
55 |
|
56 |
METHOD specify; |
57 |
y[components].fixed := TRUE; |
58 |
y[CHOICE[components]].fixed := FALSE; |
59 |
END specify; |
60 |
|
61 |
METHOD reset; |
62 |
RUN clear; |
63 |
RUN specify; |
64 |
END reset; |
65 |
|
66 |
END mixture; |
67 |
|
68 |
(* ************************************************* *) |
69 |
|
70 |
|
71 |
MODEL molar_stream; |
72 |
|
73 |
components IS_A set OF symbol_constant; |
74 |
state IS_A mixture; |
75 |
Ftot,f[components] IS_A molar_rate; |
76 |
|
77 |
components, state.components ARE_THE_SAME; |
78 |
|
79 |
|
80 |
FOR i IN components CREATE |
81 |
f_def[i]: f[i] = Ftot*state.y[i]; |
82 |
END FOR; |
83 |
|
84 |
METHODS |
85 |
|
86 |
METHOD clear; |
87 |
RUN state.clear; |
88 |
Ftot.fixed := FALSE; |
89 |
f[components].fixed := FALSE; |
90 |
END clear; |
91 |
|
92 |
METHOD seqmod; |
93 |
RUN state.specify; |
94 |
state.y[components].fixed := FALSE; |
95 |
END seqmod; |
96 |
|
97 |
METHOD specify; |
98 |
RUN seqmod; |
99 |
f[components].fixed := TRUE; |
100 |
END specify; |
101 |
|
102 |
METHOD reset; |
103 |
RUN clear; |
104 |
RUN specify; |
105 |
END reset; |
106 |
|
107 |
METHOD scale; |
108 |
FOR i IN components DO |
109 |
f[i].nominal := f[i] + 0.1{mol/s}; |
110 |
END FOR; |
111 |
Ftot.nominal := Ftot + 0.1{mol/s}; |
112 |
END scale; |
113 |
|
114 |
END molar_stream; |
115 |
|
116 |
(* ************************************************* *) |
117 |
|
118 |
|
119 |
MODEL mixer; |
120 |
|
121 |
n_inputs IS_A integer_constant; |
122 |
feed[1..n_inputs], out IS_A molar_stream; |
123 |
|
124 |
feed[1..n_inputs].components, |
125 |
out.components ARE_THE_SAME; |
126 |
|
127 |
FOR i IN out.components CREATE |
128 |
cmb[i]: out.f[i] = SUM[feed[1..n_inputs].f[i]]; |
129 |
END FOR; |
130 |
|
131 |
METHODS |
132 |
|
133 |
METHOD clear; |
134 |
RUN feed[1..n_inputs].clear; |
135 |
RUN out.clear; |
136 |
END clear; |
137 |
|
138 |
METHOD seqmod; |
139 |
END seqmod; |
140 |
|
141 |
METHOD specify; |
142 |
RUN seqmod; |
143 |
RUN feed[1..n_inputs].specify; |
144 |
END specify; |
145 |
|
146 |
METHOD reset; |
147 |
RUN clear; |
148 |
RUN specify; |
149 |
END reset; |
150 |
|
151 |
METHOD scale; |
152 |
RUN feed[1..n_inputs].scale; |
153 |
RUN out.scale; |
154 |
END scale; |
155 |
|
156 |
END mixer; |
157 |
|
158 |
(* ************************************************* *) |
159 |
|
160 |
|
161 |
MODEL reactor; |
162 |
|
163 |
feed, out IS_A molar_stream; |
164 |
feed.components, out.components ARE_THE_SAME; |
165 |
|
166 |
turnover IS_A molar_rate; |
167 |
stoich_coef[feed.components] IS_A factor; |
168 |
|
169 |
FOR i IN feed.components CREATE |
170 |
out.f[i] = feed.f[i] + stoich_coef[i]*turnover; |
171 |
END FOR; |
172 |
|
173 |
METHODS |
174 |
|
175 |
METHOD clear; |
176 |
RUN feed.clear; |
177 |
RUN out.clear; |
178 |
turnover.fixed := FALSE; |
179 |
stoich_coef[feed.components].fixed := FALSE; |
180 |
END clear; |
181 |
|
182 |
METHOD seqmod; |
183 |
turnover.fixed := TRUE; |
184 |
stoich_coef[feed.components].fixed := TRUE; |
185 |
END seqmod; |
186 |
|
187 |
METHOD specify; |
188 |
RUN seqmod; |
189 |
RUN feed.specify; |
190 |
END specify; |
191 |
|
192 |
METHOD reset; |
193 |
RUN clear; |
194 |
RUN specify; |
195 |
END reset; |
196 |
|
197 |
METHOD scale; |
198 |
RUN feed.scale; |
199 |
RUN out.scale; |
200 |
turnover.nominal := turnover.nominal+0.0001 {kg_mole/s}; |
201 |
END scale; |
202 |
|
203 |
END reactor; |
204 |
|
205 |
(* ************************************************* *) |
206 |
|
207 |
|
208 |
MODEL flash; |
209 |
|
210 |
feed,vap,liq IS_A molar_stream; |
211 |
|
212 |
feed.components, |
213 |
vap.components, |
214 |
liq.components ARE_THE_SAME; |
215 |
|
216 |
alpha[feed.components], |
217 |
ave_alpha IS_A factor; |
218 |
|
219 |
vap_to_feed_ratio IS_A fraction; |
220 |
|
221 |
vap_to_feed_ratio*feed.Ftot = vap.Ftot; |
222 |
|
223 |
FOR i IN feed.components CREATE |
224 |
cmb[i]: feed.f[i] = vap.f[i] + liq.f[i]; |
225 |
eq[i]: vap.state.y[i]*ave_alpha = alpha[i]*liq.state.y[i]; |
226 |
END FOR; |
227 |
|
228 |
METHODS |
229 |
|
230 |
METHOD clear; |
231 |
RUN feed.clear; |
232 |
RUN vap.clear; |
233 |
RUN liq.clear; |
234 |
alpha[feed.components].fixed := FALSE; |
235 |
ave_alpha.fixed := FALSE; |
236 |
vap_to_feed_ratio.fixed := FALSE; |
237 |
END clear; |
238 |
|
239 |
METHOD seqmod; |
240 |
alpha[feed.components].fixed := TRUE; |
241 |
vap_to_feed_ratio.fixed := TRUE; |
242 |
END seqmod; |
243 |
|
244 |
METHOD specify; |
245 |
RUN seqmod; |
246 |
RUN feed.specify; |
247 |
END specify; |
248 |
|
249 |
METHOD reset; |
250 |
RUN clear; |
251 |
RUN specify; |
252 |
END reset; |
253 |
|
254 |
METHOD scale; |
255 |
RUN feed.scale; |
256 |
RUN vap.scale; |
257 |
RUN liq.scale; |
258 |
END scale; |
259 |
|
260 |
END flash; |
261 |
|
262 |
(* ************************************************* *) |
263 |
|
264 |
|
265 |
MODEL splitter; |
266 |
|
267 |
n_outputs IS_A integer_constant; |
268 |
feed, out[1..n_outputs] IS_A molar_stream; |
269 |
split[1..n_outputs] IS_A fraction; |
270 |
|
271 |
feed.components, out[1..n_outputs].components ARE_THE_SAME; |
272 |
|
273 |
feed.state, |
274 |
out[1..n_outputs].state ARE_THE_SAME; |
275 |
|
276 |
FOR j IN [1..n_outputs] CREATE |
277 |
out[j].Ftot = split[j]*feed.Ftot; |
278 |
END FOR; |
279 |
|
280 |
SUM[split[1..n_outputs]] = 1.0; |
281 |
|
282 |
METHODS |
283 |
|
284 |
METHOD clear; |
285 |
RUN feed.clear; |
286 |
RUN out[1..n_outputs].clear; |
287 |
split[1..n_outputs-1].fixed := FALSE; |
288 |
END clear; |
289 |
|
290 |
METHOD seqmod; |
291 |
split[1..n_outputs-1].fixed := TRUE; |
292 |
END seqmod; |
293 |
|
294 |
METHOD specify; |
295 |
RUN seqmod; |
296 |
RUN feed.specify; |
297 |
END specify; |
298 |
|
299 |
METHOD reset; |
300 |
RUN clear; |
301 |
RUN specify; |
302 |
END reset; |
303 |
|
304 |
METHOD scale; |
305 |
RUN feed.scale; |
306 |
RUN out[1..n_outputs].scale; |
307 |
END scale; |
308 |
|
309 |
END splitter; |
310 |
|
311 |
(* ************************************************* *) |
312 |
|
313 |
|
314 |
MODEL flowsheet; |
315 |
|
316 |
m1 IS_A mixer; |
317 |
r1 IS_A reactor; |
318 |
fl1 IS_A flash; |
319 |
sp1 IS_A splitter; |
320 |
|
321 |
(* define sets *) |
322 |
|
323 |
m1.n_inputs :== 2; |
324 |
sp1.n_outputs :== 2; |
325 |
|
326 |
(* wire up flowsheet *) |
327 |
|
328 |
m1.out, r1.feed ARE_THE_SAME; |
329 |
r1.out, fl1.feed ARE_THE_SAME; |
330 |
fl1.vap, sp1.feed ARE_THE_SAME; |
331 |
sp1.out[2], m1.feed[2] ARE_THE_SAME; |
332 |
|
333 |
METHODS |
334 |
|
335 |
METHOD clear; |
336 |
RUN m1.clear; |
337 |
RUN r1.clear; |
338 |
RUN fl1.clear; |
339 |
RUN sp1.clear; |
340 |
END clear; |
341 |
|
342 |
METHOD seqmod; |
343 |
RUN m1.seqmod; |
344 |
RUN r1.seqmod; |
345 |
RUN fl1.seqmod; |
346 |
RUN sp1.seqmod; |
347 |
END seqmod; |
348 |
|
349 |
METHOD specify; |
350 |
RUN seqmod; |
351 |
RUN m1.feed[1].specify; |
352 |
END specify; |
353 |
|
354 |
METHOD reset; |
355 |
RUN clear; |
356 |
RUN specify; |
357 |
END reset; |
358 |
|
359 |
METHOD scale; |
360 |
RUN m1.scale; |
361 |
RUN r1.scale; |
362 |
RUN fl1.scale; |
363 |
RUN sp1.scale; |
364 |
END scale; |
365 |
|
366 |
END flowsheet; |
367 |
|
368 |
(* ************************************************* *) |
369 |
|
370 |
|
371 |
MODEL controller; |
372 |
|
373 |
fs IS_A flowsheet; |
374 |
conv IS_A fraction; |
375 |
key_components IS_A symbol_constant; |
376 |
fs.r1.out.f[key_components] = (1 - conv)*fs.r1.feed.f[key_components]; |
377 |
|
378 |
METHODS |
379 |
|
380 |
METHOD clear; |
381 |
RUN fs.clear; |
382 |
conv.fixed := FALSE; |
383 |
END clear; |
384 |
|
385 |
METHOD specify; |
386 |
RUN fs.specify; |
387 |
fs.r1.turnover.fixed := FALSE; |
388 |
conv.fixed := TRUE; |
389 |
END specify; |
390 |
|
391 |
METHOD reset; |
392 |
RUN clear; |
393 |
RUN specify; |
394 |
END reset; |
395 |
|
396 |
METHOD scale; |
397 |
RUN fs.scale; |
398 |
END scale; |
399 |
|
400 |
END controller; |
401 |
|
402 |
(* ************************************************* *) |
403 |
|
404 |
|
405 |
MODEL test_flowsheet REFINES flowsheet; |
406 |
|
407 |
m1.out.components :== ['A','B','C']; |
408 |
|
409 |
METHODS |
410 |
|
411 |
METHOD default_self; |
412 |
(* no-op. here to avoid STOP statement. *) |
413 |
END default_self; |
414 |
|
415 |
METHOD values; |
416 |
m1.feed[1].f['A'] := 0.005 {kg_mole/s}; |
417 |
m1.feed[1].f['B'] := 0.095 {kg_mole/s}; |
418 |
m1.feed[1].f['C'] := 0.0 {kg_mole/s}; |
419 |
|
420 |
r1.stoich_coef['A'] := 0; |
421 |
r1.stoich_coef['B'] := -1; |
422 |
r1.stoich_coef['C'] := 1; |
423 |
|
424 |
fl1.alpha['A'] := 12.0; |
425 |
fl1.alpha['B'] := 10.0; |
426 |
fl1.alpha['C'] := 1.0; |
427 |
fl1.vap_to_feed_ratio := 0.9; |
428 |
fl1.ave_alpha := 5.0; |
429 |
|
430 |
sp1.split[1] := 0.01; |
431 |
|
432 |
fl1.liq.Ftot := m1.feed[1].f['B']; |
433 |
END values; |
434 |
|
435 |
END test_flowsheet; |
436 |
|
437 |
(* ************************************************* *) |
438 |
|
439 |
|
440 |
MODEL test_controller REFINES controller; |
441 |
|
442 |
fs IS_REFINED_TO test_flowsheet; |
443 |
key_components :== 'B'; |
444 |
|
445 |
METHODS |
446 |
|
447 |
METHOD default_self; |
448 |
(* no-op. here to avoid STOP statement. *) |
449 |
END default_self; |
450 |
|
451 |
METHOD values; |
452 |
RUN fs.values; |
453 |
conv := 0.07; |
454 |
END values; |
455 |
|
456 |
END test_controller; |
457 |
|
458 |
|
459 |
(* |
460 |
* simple_fs.a4c |
461 |
* by Arthur W. Westerberg |
462 |
* Part of the ASCEND Library |
463 |
* $Date: 1998/06/17 19:28:37 $ |
464 |
* $Revision: 1.2 $ |
465 |
* $Author: mthomas $ |
466 |
* $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/simple_fs.a4c,v $ |
467 |
* |
468 |
* This file is part of the ASCEND Modeling Library. |
469 |
* |
470 |
* Copyright (C) 1994 - 1998 Carnegie Mellon University |
471 |
* |
472 |
* The ASCEND Modeling Library is free software; you can redistribute |
473 |
* it and/or modify it under the terms of the GNU General Public |
474 |
* License as published by the Free Software Foundation; either |
475 |
* version 2 of the License, or (at your option) any later version. |
476 |
* |
477 |
* The ASCEND Modeling Library is distributed in hope that it |
478 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
479 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
480 |
* See the GNU General Public License for more details. |
481 |
* |
482 |
* You should have received a copy of the GNU General Public License |
483 |
* along with the program; if not, write to the Free Software |
484 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
485 |
* the file named COPYING. |
486 |
*) |