1 |
PROVIDE "basemodel.a4l"; |
2 |
|
3 |
(* |
4 |
* basemodel.a4l |
5 |
* by Benjamin A. Allan |
6 |
* Part of the ASCEND Library |
7 |
* $Date: 1998/06/17 14:15:10 $ |
8 |
* $Revision: 1.3 $ |
9 |
* $Author: mthomas $ |
10 |
* $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/basemodel.a4l,v $ |
11 |
* |
12 |
* This file is part of the ASCEND Modeling Library. |
13 |
* |
14 |
* Copyright (C) 1998 Carnegie Mellon University |
15 |
* |
16 |
* The ASCEND Modeling Library is free software; you can redistribute |
17 |
* it and/or modify it under the terms of the GNU General Public |
18 |
* License as published by the Free Software Foundation; either |
19 |
* version 2 of the License, or (at your option) any later version. |
20 |
* |
21 |
* The ASCEND Modeling Library is distributed in hope that it |
22 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
23 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
24 |
* See the GNU General Public License for more details. |
25 |
* |
26 |
* You should have received a copy of the GNU General Public License |
27 |
* along with the program; if not, write to the Free Software |
28 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
29 |
* the file named COPYING. |
30 |
*) |
31 |
|
32 |
(*============================================================================* |
33 |
|
34 |
B A S E M O D E L . A 4 L |
35 |
------------------------- |
36 |
|
37 |
AUTHOR: Benjamin A. Allan |
38 |
|
39 |
DATES: 03/98 - Original Code |
40 |
|
41 |
CONTENTS: Basic definitions cmu libraries and standard |
42 |
methods. |
43 |
This file is necessary for all |
44 |
other CMU authored ASCEND models to work in ASCEND IV. |
45 |
|
46 |
*============================================================================*) |
47 |
|
48 |
MODEL catch_Word_model (* Bill Gates sacrificial goat *); |
49 |
(* This MODEL does nothing. |
50 |
* Normally catch_Word_model just gets parsed and ignored. |
51 |
* |
52 |
* If the user has tried to read a Microsoft Word binary file, Tcl file, |
53 |
* or some other piece of junk as if it were an ASCEND MODEL |
54 |
* source file, then catch_Word_model will die on an unknown |
55 |
* syntax error. |
56 |
* While catch_Word_model is dying the parser returns a good |
57 |
* starting condition. |
58 |
* |
59 |
* Here is the message of recovery when this MODEL fails: |
60 |
Asc-Error: Model definition "catch_Word_model" abandoned due to syntax errors. |
61 |
Asc-Error: Rejected "catch_Word_model" at line basemodel.a4l:62. |
62 |
*) |
63 |
END catch_Word_model; |
64 |
|
65 |
(* First define the standard methods, or stand-ins which will tell |
66 |
* us when a standard method has not been written. |
67 |
*) |
68 |
ADD METHODS IN DEFINITION MODEL; |
69 |
|
70 |
METHOD ClearAll; |
71 |
|
72 |
NOTES 'purpose' SELF { |
73 |
This method finds anything that is a solver_var and changes |
74 |
the .fixed flag on the var to FALSE. |
75 |
|
76 |
This method does not change .included flags on relations |
77 |
or return boolean, integer, or symbol variables to a |
78 |
default value. |
79 |
} END NOTES; |
80 |
|
81 |
EXTERNAL asc_free_all_variables(SELF); |
82 |
END ClearAll; |
83 |
|
84 |
(* |
85 |
* Geniuses make more mistakes than anyone else -- because they |
86 |
* try more things that anyone else. Part (perhaps a very large |
87 |
* part) of what makes a genius different from the rest of |
88 |
* humanity is that they quickly recognize their own mistakes |
89 |
* and move on to try something else before anyone notices |
90 |
* they screwed up! Solving a problem as far and as fast as you |
91 |
* can, then going back to criticize every aspect of the solution |
92 |
* with an eye to improving it is how you usually discover right answers. |
93 |
* |
94 |
* The authors of ASCEND (geniuses or not we'll |
95 |
* leave to our users to decide) have found that it is |
96 |
* best to do things such as writing mathematical MODELs and |
97 |
* writing mathematical modeling software in ways which |
98 |
* makes our mistakes (or your mistakes) very easy to detect. |
99 |
* |
100 |
* Below we describe a methodology (pun intended) which can |
101 |
* help make anyone who can solve a quadratic equation |
102 |
* a mathematical modeling expert. This methodology helps |
103 |
* you to avoid screwing up and to find out about it when you have. |
104 |
* |
105 |
* The ASCEND system will not force you to write standard |
106 |
* methods in your models. :-( METHODs of the sort we advocate |
107 |
* here make your MODELs much easier to use and |
108 |
* much more reliable. They pay off in the short run as well |
109 |
* as the long run. These are _guidelines_, not _laws_: real |
110 |
* genius requires knowing when to color outside the lines. :-) |
111 |
* |
112 |
* If you do not write the standard methods, your MODEL will |
113 |
* inherit the ones given here. The "ClearAll" and "reset" |
114 |
* methods here will work for you if you followed the guidelines. |
115 |
* The other methods contain STOP statements which will warn you |
116 |
* that you have skipped something important, should you accidentally |
117 |
* end up calling one of them. |
118 |
* |
119 |
* The following methods should be redefined by each |
120 |
* reusable library MODEL that REFINES this root MODEL. |
121 |
* Models that do not supply proper versions of these |
122 |
* (and possibly other) methods are very hard to reuse. |
123 |
* |
124 |
* The premise of this method design is that we can |
125 |
* write the _self methods incrementally, building on the |
126 |
* already tested methods of previous MODEL parts we are |
127 |
* reusing. In this way we never have to write a single huge method |
128 |
* that directly checks 100s of variables in a hierarchy. |
129 |
* |
130 |
* The _all methods are methods which simply "top off" the |
131 |
* _self methods. With an _all method, you can treat |
132 |
* just a part of a larger simulation already built |
133 |
* as a self-contained simulation. |
134 |
* |
135 |
*) |
136 |
|
137 |
(* |
138 |
* Usually discovery of the information you need to write the methods |
139 |
* proceeds in the order that they appear below: |
140 |
* check, default, specify, bound, scale. |
141 |
*) |
142 |
|
143 |
METHOD check_self; |
144 |
NOTES 'purpose' SELF { |
145 |
This method should be written first, though it is run |
146 |
last. Just like they taught you in elementary school, |
147 |
always check your work. Start by defining criteria for a |
148 |
successful solution that will not be included in the |
149 |
equations solved and then computing those in this method. |
150 |
As you develop your MODEL, you should expect to revise the |
151 |
check method from time to time, if you are learning |
152 |
anything about the MODEL. We frequently change our |
153 |
definition of success. |
154 |
|
155 |
When a mathematical MODEL is solved, the assumptions that |
156 |
went into writing (deriving) the equations should be |
157 |
checked. Usually there are redundant equations available |
158 |
(more than one way to state the physical MODEL |
159 |
mathematically). These should be used to check the |
160 |
particularly tricky bits of the MODEL. |
161 |
|
162 |
Check that the physical or intuitive (qualitative) |
163 |
relationships among variables ch you expect to hold are |
164 |
TRUE, especially if you have not written such relationships |
165 |
in terms of inequalities in the MODEL equations. |
166 |
|
167 |
In some models, checking the variable values against |
168 |
absolute physical limits (temperature > 0{K} and |
169 |
temperature < Tcritical for example) may be all that is |
170 |
necessary or possible. Do not check variable values against |
171 |
their .lower_bound or .upper_bound, as any decent algebraic |
172 |
solver or modeling system will do this for you. |
173 |
|
174 |
If a check fails, use a STOP or ERROR statement to notify |
175 |
yourself (or you MODEL using customer) that the solution |
176 |
may be bogus. |
177 |
|
178 |
Currently only STOP is implemented. |
179 |
STOP raises an error signal and issues an error message; |
180 |
STOP normally also stops further execution of the method |
181 |
and returns control to a higher level, though there are |
182 |
interactive tools to force method execution to continue. |
183 |
STOP does not crash the ASCEND system. |
184 |
|
185 |
} END NOTES; |
186 |
|
187 |
STOP {Error! Standard method "check_self" called but not written in MODEL.}; |
188 |
|
189 |
END check_self; |
190 |
|
191 |
METHOD check_all; |
192 |
|
193 |
NOTES 'purpose' SELF { |
194 |
When solving only a part of a simulation, it is necessary to check |
195 |
the models and variables passed into the part as well as the |
196 |
locally defined parts and variables. This method should check |
197 |
all the received models and variables, then check the local |
198 |
stuff. |
199 |
} END NOTES; |
200 |
|
201 |
STOP {Error! Standard method "check_all" called but not written in MODEL.}; |
202 |
RUN check_self; (* intentionally _second_ *) |
203 |
|
204 |
END check_all; |
205 |
|
206 |
METHOD defaults; |
207 |
(* |
208 |
* This is a kluge for interfaces that still think of |
209 |
* 'defaults' as the standard method. |
210 |
*) |
211 |
RUN default_self; |
212 |
STOP {GUI (or somebody) called non-standard method defaults. Call forwarded to default_self before stopping here.}; |
213 |
END defaults; |
214 |
|
215 |
METHOD default_self; |
216 |
NOTES 'purpose' SELF { |
217 |
This method should set default values for any variables |
218 |
declared locally (IS_A) to the MODEL. It should run |
219 |
default_self on _all_ the models that are declared locally |
220 |
(with IS_A) in the MODEL also. If the atoms you use to |
221 |
define your variables have a suitable default already, then |
222 |
you do not need to assign them a default in this method. |
223 |
|
224 |
This method should not run any methods on MODEL parts that |
225 |
come via WILL_BE in the definition's parameter list. This |
226 |
method also should not change the values of variables that |
227 |
are passed in through the parameter list. |
228 |
|
229 |
Sometimes there will be nothing for this method to do. |
230 |
Define it anyway, leaving it empty. |
231 |
|
232 |
When a top-level simulation is built by the compiler, this |
233 |
method will be run at the end of compilation by the |
234 |
compiler. |
235 |
} END NOTES; |
236 |
|
237 |
STOP {Error! Standard method "default_self" called but not written in MODEL.}; |
238 |
END default_self; |
239 |
|
240 |
METHOD default_all; |
241 |
|
242 |
NOTES 'purpose' SELF { |
243 |
This method assumes that the arguments to the MODEL |
244 |
instance have not been properly initialized, as is |
245 |
frequently the case in one-off modeling efforts. This |
246 |
method should run the default_self method on each of the |
247 |
parts received through the parameter list and should give |
248 |
appropriate default values to any variables received |
249 |
through the parameter list. After these have been done, it |
250 |
should then call default_self to take care of all locally |
251 |
declared default needs. |
252 |
} END NOTES; |
253 |
|
254 |
STOP {Error! Standard method "default_all" called but not written in MODEL.}; |
255 |
RUN default_self; |
256 |
END default_all; |
257 |
|
258 |
METHOD specify; |
259 |
NOTES 'purpose' SELF { |
260 |
* Assuming ClearAll has been run on the MODEL, this method |
261 |
* should get the MODEL to a condition called 'square': |
262 |
* the case where there are as many variables with .fixed == FALSE |
263 |
* as there equations available to compute them. |
264 |
* This is one of the hardest tasks ever invented by mathematicians |
265 |
* if you go about it in the wrong way. We think we know the right way. |
266 |
* |
267 |
* Actually, 'square' is a bit trickier to achieve |
268 |
* than simply counting equations and variables. |
269 |
* Solver, such as QRSlv in ASCEND, may help greatly with the bookkeeping. |
270 |
* |
271 |
The general approach is to: |
272 |
|
273 |
(1) Run "specify" for all the parts (both passed in and locally defined) |
274 |
that are not passed on into other parts. |
275 |
|
276 |
(2) Fix up (by tweaking .fixed flags on variables) any difficulties |
277 |
that arise when parts compete to calculate the same variable. |
278 |
|
279 |
(3) Use the remaining new local variables to take care of any leftover |
280 |
equations among the parts and any new equations written locally. |
281 |
|
282 |
At all steps 1-3 |
283 |
Pay special attention to indexed variables used in |
284 |
indexed equations; frequently you must fix or free N or |
285 |
N-1 variables of a set sized N, if there are N matching equations. |
286 |
In general, if you think you have specify correctly written, change |
287 |
the sizes of all the sets in your MODEL by one and then by two |
288 |
members. If your specify method still works, you are using sets |
289 |
correctly. |
290 |
|
291 |
When writing models that combine parts which do not share |
292 |
very well, or which both try to compute the same variable |
293 |
in different ways, it may even be necessary to write a WHEN |
294 |
statement to selectively TURN OFF the conflicting equations |
295 |
or MODEL fragments. An object or equation USEd in a WHEN |
296 |
statement is turned off by default and becomes a part of |
297 |
the solved MODEL only when the conditions of some CASE |
298 |
which refers to that object are matched. |
299 |
|
300 |
The setting of boolean, integer, and symbol variables which |
301 |
are controlling conditions of WHEN and SWITCH statements |
302 |
should be taken care of in the specify method. |
303 |
|
304 |
There is no 'one perfect "specify"' for all purposes. This |
305 |
routine should merely define a reasonably useful base |
306 |
configuration of the MODEL. |
307 |
|
308 |
Other specify_whatElseYouWant methods can (should) also be |
309 |
written. |
310 |
|
311 |
The name of a method is a communication tool. Please use |
312 |
meaningful names as long as necessary to tell what the |
313 |
method does. Avoid cryptic abbreviations and hyper- |
314 |
specialized jargon known only to you and your three friends |
315 |
when you are naming methods; however, do not shy away from |
316 |
technical terms common to the engineering domain in which |
317 |
you are modeling. |
318 |
|
319 |
} END NOTES; |
320 |
|
321 |
STOP {Error! Standard method "specify" called but not written in MODEL.}; |
322 |
|
323 |
END specify; |
324 |
|
325 |
METHOD reset; |
326 |
NOTES 'purpose' SELF { |
327 |
This method gets the MODEL to some standard starting state, |
328 |
though not necessarily the most useful starting state for a |
329 |
particular application. In Chem. Eng. terms, this method |
330 |
establishes a base case. |
331 |
|
332 |
There is no 'one perfect "reset"' for all purposes. This |
333 |
routine should merely define a reasonably useful base |
334 |
configuration of the MODEL. |
335 |
|
336 |
Other reset_whatElseYouWant methods can (should) also be |
337 |
written. |
338 |
|
339 |
Normally you do not need to write this method: your models |
340 |
will inherit this one unless you override it (redefine it) |
341 |
in your MODEL. |
342 |
} |
343 |
END NOTES; |
344 |
|
345 |
RUN ClearAll; |
346 |
RUN specify; |
347 |
|
348 |
END reset; |
349 |
|
350 |
METHOD bound_self; |
351 |
NOTES 'purpose' SELF { |
352 |
Much of the art of nonlinear physical modeling is in |
353 |
bounding the solution. |
354 |
|
355 |
This method should update the bounds on _locally_ defined |
356 |
(IS_A) variables and IS_A defined MODEL parts. Updating |
357 |
bounds requires some care. For example, the bounds on |
358 |
fractions frequently don't need updating. |
359 |
|
360 |
A common formula for updating bounds is to define a region |
361 |
around the current value of the variable. A linear region |
362 |
size formula, as an example, would be: |
363 |
|
364 |
v.upper_bound := v + boundwidth * v.nominal; |
365 |
v.lower_bound := v - boundwidth * v.nominal; |
366 |
|
367 |
Care must be taken that such a formula does not move the |
368 |
bounds (particularly lower bounds) out so far as to allow |
369 |
non-physical solutions. Logarithmic bounding regions are |
370 |
also simple to calculate. |
371 |
|
372 |
Here boundwidth IS_A bound_width; |
373 |
boundwidth is a real variable (but not a solver_var) or a |
374 |
value you can use to determine how much "wiggle-room" you |
375 |
want to give a solver. Small powers of 4 and 10 are usually |
376 |
good values of boundwidth. |
377 |
|
378 |
Too small a boundwidth can cut off the portion of number |
379 |
space where the solution is found. Too large a bound width |
380 |
can allow solvers to wander for great distances in |
381 |
uninteresting regions of the number space. |
382 |
|
383 |
This method should not bound variables passed into the |
384 |
MODEL definition or parts passed into the definition. |
385 |
} END NOTES; |
386 |
|
387 |
STOP {Error! Standard method "bound_self" called but not written in MODEL.}; |
388 |
END bound_self; |
389 |
|
390 |
METHOD bound_all; |
391 |
NOTES 'purpose' SELF { |
392 |
This method should be like bound_self except that it bounds the |
393 |
passed in variables and calls bound_self on the passed in parts. |
394 |
It should then call bound_self. |
395 |
} END NOTES; |
396 |
|
397 |
STOP {Error! Standard method "bound_all" called but not written in MODEL.}; |
398 |
RUN bound_self; |
399 |
END bound_all; |
400 |
|
401 |
METHOD scale_self; |
402 |
NOTES 'purpose' SELF { |
403 |
Most nonlinear (and many linear) models cannot be solved without |
404 |
proper scaling of the variables. |
405 |
|
406 |
This method should reset the .nominal value on every real |
407 |
variable in need of scaling. It should then call the |
408 |
scale_self method on all the locally defined (IS_A) parts |
409 |
of the MODEL. 0.0 is the worst possible nominal value. A |
410 |
proper nominal is one such that you expect at the solution |
411 |
the quantity |
412 |
|
413 |
abs(variable/(variable.nominal)) |
414 |
|
415 |
to be around 1 (in the range of [0.1..10] or [0.01..100]). |
416 |
|
417 |
Variables (like fractions) bounded such that they cannot be |
418 |
too far away from 1.0 in magnitude probably don't need scaling |
419 |
most of the time if they are also bounded away from 0.0. |
420 |
|
421 |
Some solvers, but not all, will attempt to scale the |
422 |
equations and variables by heuristic matrix-based methods. |
423 |
This works, but inconsistently; user-defined scaling is |
424 |
generaly much superior. |
425 |
|
426 |
ASCEND makes it easy to do. You scale the variables, which |
427 |
can only be done well by knowing something about where the |
428 |
solution is going to be found (by being an engineer, for |
429 |
example.) Then ASCEND can calculate an appropriate |
430 |
equation-scaling by efficient symbolic methods. |
431 |
|
432 |
This method should not change the scaling of models and |
433 |
variables that are received through the parameter list of |
434 |
the MODEL. |
435 |
} END NOTES; |
436 |
|
437 |
STOP {Error! Standard method "scale_self" called but not written in MODEL.}; |
438 |
END scale_self; |
439 |
|
440 |
METHOD scale_all; |
441 |
NOTES 'purpose' SELF { |
442 |
This method should be like scale_self above except that it also |
443 |
should scale the variables and models received through the |
444 |
parameter list. It should then call scale_self to take care of |
445 |
the local variables and models. |
446 |
} END NOTES; |
447 |
|
448 |
STOP {Error! Standard method "scale_all" called but not written in MODEL.}; |
449 |
RUN scale_self; |
450 |
END scale_all; |
451 |
END METHODS; |
452 |
|
453 |
MODEL cmumodel(); |
454 |
NOTES |
455 |
'purpose' SELF { |
456 |
This MODEL does nothing except provide a root |
457 |
for a collection of loosely related models. |
458 |
If it happens to reveal a few bugs in the software, |
459 |
and perhaps masks others, well, what me worry? |
460 |
BAA, 8/97. |
461 |
} |
462 |
'methods' SELF { |
463 |
This MODEL also provides a hook to put in candidates for |
464 |
becoming ascBuiltin global methods. Global methods may be |
465 |
overridden by local definitions. |
466 |
BAA, 3/98. |
467 |
} |
468 |
END NOTES; |
469 |
|
470 |
END cmumodel; |
471 |
|
472 |
MODEL testcmumodel(); |
473 |
(* |
474 |
* All CMU test models, of whatever sort should ultimately be |
475 |
* rooted here or be a final refinement of a reusable MODEL. |
476 |
*) |
477 |
METHODS |
478 |
METHOD values; |
479 |
(* |
480 |
* In a final application MODEL, you should record at least one set of |
481 |
* input values (values of the fixed variables and guesses of key |
482 |
* solved-for variables) that leads to a good solution. |
483 |
* Do this so noone need reinvent that set the next time |
484 |
* you use the MODEL or someone picks the MODEL up after you. |
485 |
*) |
486 |
STOP {Error! Standard method "values" called but not written in MODEL.}; |
487 |
END values; |
488 |
|
489 |
METHOD specify; |
490 |
STOP {Error! Standard method "specify" called but not written in test MODEL.}; |
491 |
END specify; |
492 |
(* |
493 |
METHOD ClearAll; |
494 |
EXTERNAL asc_free_all_variables(SELF); |
495 |
END ClearAll; |
496 |
|
497 |
METHOD reset; |
498 |
(* This method gets the MODEL to some standard starting state, |
499 |
* though not necessarily the most useful starting state for |
500 |
* a particular application. In Chem. Eng. terms, this method |
501 |
* establishes a base case. |
502 |
* There is no 'one perfect "reset"' for all purposes. This |
503 |
* routine should merely define a reasonably useful base configuration |
504 |
* of the MODEL. |
505 |
* Other reset_whatElseYouWant methods can (should) also be |
506 |
* written. |
507 |
* |
508 |
* Normally you do not need to write this method: your models |
509 |
* will inherit this one unless you override it (redefine it) |
510 |
* in your MODEL. |
511 |
*) |
512 |
RUN ClearAll; |
513 |
RUN specify; |
514 |
END reset; |
515 |
*) |
516 |
END testcmumodel; |
517 |
|
518 |
MODEL your_site_models(); |
519 |
(* if you create a library to share with the net which is |
520 |
* not just an end application of Carnegie Mellon models, |
521 |
* please create an empy root MODEL such as this and use |
522 |
* it as the origin of your library in the same way that |
523 |
* we use cmumodel as the origin of our libraries. |
524 |
* Thank you. |
525 |
*) |
526 |
END your_site_models; |