Parent Directory | Revision Log

Revision **2651** -
(**show annotations**)
(**download**)
(**as text**)

*Thu Dec 13 07:29:48 2012 UTC*
(11 years, 6 months ago)
by *jpye*

File MIME type: text/x-ascend

File size: 19334 byte(s)

File MIME type: text/x-ascend

File size: 19334 byte(s)

Fixing GPL header, removing postal address (rpmlint incorrect-fsf-address)

1 | (* ASCEND modelling environment |

2 | Copyright (C) 1998, 2007 Carnegie Mellon University |

3 | |

4 | This program is free software; you can redistribute it and/or modify |

5 | it under the terms of the GNU General Public License as published by |

6 | the Free Software Foundation; either version 2, or (at your option) |

7 | any later version. |

8 | |

9 | This program is distributed in the hope that it will be useful, |

10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |

11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |

12 | GNU General Public License for more details. |

13 | |

14 | You should have received a copy of the GNU General Public License |

15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |

16 | *) |

17 | PROVIDE "basemodel.a4l"; |

18 | (* |

19 | basemodel.a4l, by Benjamin A. Allan 03/98 - Original Code |

20 | |

21 | Basic definitions cmu libraries and standard methods. |

22 | This file is necessary for all other CMU authored ASCEND models to work |

23 | in ASCEND IV. |

24 | *) |

25 | |

26 | MODEL catch_Word_model (* Bill Gates sacrificial goat *); |

27 | (* This MODEL does nothing. |

28 | * Normally catch_Word_model just gets parsed and ignored. |

29 | * |

30 | * If the user has tried to read a Microsoft Word binary file, Tcl file, |

31 | * or some other piece of junk as if it were an ASCEND MODEL |

32 | * source file, then catch_Word_model will die on an unknown |

33 | * syntax error. |

34 | * While catch_Word_model is dying the parser returns a good |

35 | * starting condition. |

36 | * |

37 | * Here is the message of recovery when this MODEL fails: |

38 | Asc-Error: Model definition "catch_Word_model" abandoned due to syntax errors. |

39 | Asc-Error: Rejected "catch_Word_model" at line basemodel.a4l:62. |

40 | |

41 | @TODO document how this works |

42 | *) |

43 | END catch_Word_model; |

44 | |

45 | (* First define the standard methods, or stand-ins which will tell |

46 | * us when a standard method has not been written. |

47 | *) |

48 | ADD METHODS IN DEFINITION MODEL; |

49 | |

50 | METHOD ClearAll; |

51 | |

52 | NOTES 'purpose' SELF { |

53 | This method finds anything that is a solver_var and changes |

54 | the .fixed flag on the var to FALSE. |

55 | |

56 | This method does not change .included flags on relations |

57 | or return boolean, integer, or symbol variables to a |

58 | default value. |

59 | } END NOTES; |

60 | |

61 | EXTERNAL asc_free_all_variables(SELF); |

62 | END ClearAll; |

63 | |

64 | (* |

65 | * Geniuses make more mistakes than anyone else -- because they |

66 | * try more things that anyone else. Part (perhaps a very large |

67 | * part) of what makes a genius different from the rest of |

68 | * humanity is that they quickly recognize their own mistakes |

69 | * and move on to try something else before anyone notices |

70 | * they screwed up! Solving a problem as far and as fast as you |

71 | * can, then going back to criticize every aspect of the solution |

72 | * with an eye to improving it is how you usually discover right answers. |

73 | * |

74 | * The authors of ASCEND (geniuses or not we'll |

75 | * leave to our users to decide) have found that it is |

76 | * best to do things such as writing mathematical MODELs and |

77 | * writing mathematical modeling software in ways which |

78 | * makes our mistakes (or your mistakes) very easy to detect. |

79 | * |

80 | * Below we describe a methodology (pun intended) which can |

81 | * help make anyone who can solve a quadratic equation |

82 | * a mathematical modeling expert. This methodology helps |

83 | * you to avoid screwing up and to find out about it when you have. |

84 | * |

85 | * The ASCEND system will not force you to write standard |

86 | * methods in your models. :-( METHODs of the sort we advocate |

87 | * here make your MODELs much easier to use and |

88 | * much more reliable. They pay off in the short run as well |

89 | * as the long run. These are _guidelines_, not _laws_: real |

90 | * genius requires knowing when to color outside the lines. :-) |

91 | * |

92 | * If you do not write the standard methods, your MODEL will |

93 | * inherit the ones given here. The "ClearAll" and "reset" |

94 | * methods here will work for you if you followed the guidelines. |

95 | * The other methods contain STOP statements which will warn you |

96 | * that you have skipped something important, should you accidentally |

97 | * end up calling one of them. |

98 | * |

99 | * The following methods should be redefined by each |

100 | * reusable library MODEL that REFINES this root MODEL. |

101 | * Models that do not supply proper versions of these |

102 | * (and possibly other) methods are very hard to reuse. |

103 | * |

104 | * The premise of this method design is that we can |

105 | * write the _self methods incrementally, building on the |

106 | * already tested methods of previous MODEL parts we are |

107 | * reusing. In this way we never have to write a single huge method |

108 | * that directly checks 100s of variables in a hierarchy. |

109 | * |

110 | * The _all methods are methods which simply "top off" the |

111 | * _self methods. With an _all method, you can treat |

112 | * just a part of a larger simulation already built |

113 | * as a self-contained simulation. |

114 | * |

115 | *) |

116 | |

117 | (* |

118 | * Usually discovery of the information you need to write the methods |

119 | * proceeds in the order that they appear below: |

120 | * check, default, specify, bound, scale. |

121 | *) |

122 | |

123 | METHOD check_self; |

124 | NOTES 'purpose' SELF { |

125 | This method should be written first, though it is run |

126 | last. Just like they taught you in elementary school, |

127 | always check your work. Start by defining criteria for a |

128 | successful solution that will not be included in the |

129 | equations solved and then computing those in this method. |

130 | As you develop your MODEL, you should expect to revise the |

131 | check method from time to time, if you are learning |

132 | anything about the MODEL. We frequently change our |

133 | definition of success. |

134 | |

135 | When a mathematical MODEL is solved, the assumptions that |

136 | went into writing (deriving) the equations should be |

137 | checked. Usually there are redundant equations available |

138 | (more than one way to state the physical MODEL |

139 | mathematically). These should be used to check the |

140 | particularly tricky bits of the MODEL. |

141 | |

142 | Check that the physical or intuitive (qualitative) |

143 | relationships among variables ch you expect to hold are |

144 | TRUE, especially if you have not written such relationships |

145 | in terms of inequalities in the MODEL equations. |

146 | |

147 | In some models, checking the variable values against |

148 | absolute physical limits (temperature > 0{K} and |

149 | temperature < Tcritical for example) may be all that is |

150 | necessary or possible. Do not check variable values against |

151 | their .lower_bound or .upper_bound, as any decent algebraic |

152 | solver or modeling system will do this for you. |

153 | |

154 | If a check fails, use a STOP or ERROR statement to notify |

155 | yourself (or you MODEL using customer) that the solution |

156 | may be bogus. |

157 | |

158 | Currently only STOP is implemented. |

159 | STOP raises an error signal and issues an error message; |

160 | STOP normally also stops further execution of the method |

161 | and returns control to a higher level, though there are |

162 | interactive tools to force method execution to continue. |

163 | STOP does not crash the ASCEND system. |

164 | |

165 | } END NOTES; |

166 | |

167 | (* STOP {Error! Standard method "check_self" called but not written in MODEL.}; *) |

168 | |

169 | END check_self; |

170 | |

171 | METHOD check_all; |

172 | |

173 | NOTES 'purpose' SELF { |

174 | When solving only a part of a simulation, it is necessary to check |

175 | the models and variables passed into the part as well as the |

176 | locally defined parts and variables. This method should check |

177 | all the received models and variables, then check the local |

178 | stuff. |

179 | } END NOTES; |

180 | |

181 | (* STOP {Error! Standard method "check_all" called but not written in MODEL.}; *) |

182 | RUN check_self; (* intentionally _second_ *) |

183 | |

184 | END check_all; |

185 | |

186 | METHOD defaults; |

187 | (* |

188 | * This is a kluge for interfaces that still think of |

189 | * 'defaults' as the standard method. |

190 | *) |

191 | RUN default_self; |

192 | STOP {GUI (or somebody) called non-standard method defaults. Call forwarded to default_self before stopping here.}; |

193 | END defaults; |

194 | |

195 | METHOD on_load; |

196 | NOTES 'purpose' SELF { |

197 | This method adds improved ability to perform stuff when a model is first loaded. |

198 | By default, just 'default_self' will be run (this was the previous behaviour). |

199 | Any model that has an on_load method can override this behaviour however. |

200 | Note that this behaviour applies only in the C++/python interface at this stage. |

201 | } END NOTES; |

202 | RUN default_all; |

203 | END on_load; |

204 | |

205 | METHOD default; |

206 | NOTES 'purpose' SELF { |

207 | This method exists for the purpose ofOVERRIDING atom defaults in the local |

208 | MODEL. Hopefully this approach can replace the current practise of writing |

209 | 'default_self' methods for most MODELs. It should be superior, since using |

210 | 'default' instead of 'default_self' will always result in ALL variables in a |

211 | model being reset to default values, rather than only those explicitly stated |

212 | by the modeller. |

213 | } END NOTES; |

214 | (*STOP {it works!};*) |

215 | (* nothing here *) |

216 | END default; |

217 | |

218 | METHOD default_self; |

219 | NOTES 'purpose' SELF { |

220 | This method should set default values for any variables |

221 | declared locally (IS_A) to the MODEL. It should run |

222 | default_self on _all_ the models that are declared locally |

223 | (with IS_A) in the MODEL also. If the atoms you use to |

224 | define your variables have a suitable default already, then |

225 | you do not need to assign them a default in this method. |

226 | |

227 | This method should not run any methods on MODEL parts that |

228 | come via WILL_BE in the definition's parameter list. This |

229 | method also should not change the values of variables that |

230 | are passed in through the parameter list. |

231 | |

232 | Sometimes there will be nothing for this method to do. |

233 | Define it anyway, leaving it empty. |

234 | |

235 | When a top-level simulation is built by the compiler, this |

236 | method will be run at the end of compilation by the |

237 | compiler. See notes in on_load method for new behaviour in |

238 | the PyGTK GUI. |

239 | } END NOTES; |

240 | EXTERNAL defaultself_visit_childatoms(SELF); |

241 | EXTERNAL defaultself_visit_submodels(SELF); (* overwrite ATOM defaults explicit nested code if needed *) |

242 | RUN default; (* local overrides *) |

243 | END default_self; |

244 | |

245 | METHOD default_all; |

246 | NOTES 'purpose' SELF { |

247 | This method assumes that the arguments to the MODEL |

248 | instance have not been properly initialized, as is |

249 | frequently the case in one-off modeling efforts. This |

250 | method should run the default_self method on each of the |

251 | parts received through the parameter list and should give |

252 | appropriate default values to any variables received |

253 | through the parameter list. After these have been done, it |

254 | should then call default_self to take care of all locally |

255 | declared default needs. |

256 | } END NOTES; |

257 | (* INITIALISATION OF PARAMETERS IS NOT IMPLEMENTED YET *) |

258 | RUN default_self; |

259 | END default_all; |

260 | |

261 | METHOD specify; |

262 | NOTES 'purpose' SELF { |

263 | * Assuming ClearAll has been run on the MODEL, this method |

264 | * should get the MODEL to a condition called 'square': |

265 | * the case where there are as many variables with .fixed == FALSE |

266 | * as there equations available to compute them. |

267 | * This is one of the hardest tasks ever invented by mathematicians |

268 | * if you go about it in the wrong way. We think we know the right way. |

269 | * |

270 | * Actually, 'square' is a bit trickier to achieve |

271 | * than simply counting equations and variables. |

272 | * Solver, such as QRSlv in ASCEND, may help greatly with the bookkeeping. |

273 | * |

274 | The general approach is to: |

275 | |

276 | (1) Run "specify" for all the parts (both passed in and locally defined) |

277 | that are not passed on into other parts. |

278 | |

279 | (2) Fix up (by tweaking .fixed flags on variables) any difficulties |

280 | that arise when parts compete to calculate the same variable. |

281 | |

282 | (3) Use the remaining new local variables to take care of any leftover |

283 | equations among the parts and any new equations written locally. |

284 | |

285 | At all steps 1-3 |

286 | Pay special attention to indexed variables used in |

287 | indexed equations; frequently you must fix or free N or |

288 | N-1 variables of a set sized N, if there are N matching equations. |

289 | In general, if you think you have specify correctly written, change |

290 | the sizes of all the sets in your MODEL by one and then by two |

291 | members. If your specify method still works, you are using sets |

292 | correctly. |

293 | |

294 | When writing models that combine parts which do not share |

295 | very well, or which both try to compute the same variable |

296 | in different ways, it may even be necessary to write a WHEN |

297 | statement to selectively TURN OFF the conflicting equations |

298 | or MODEL fragments. An object or equation USEd in a WHEN |

299 | statement is turned off by default and becomes a part of |

300 | the solved MODEL only when the conditions of some CASE |

301 | which refers to that object are matched. |

302 | |

303 | The setting of boolean, integer, and symbol variables which |

304 | are controlling conditions of WHEN and SWITCH statements |

305 | should be taken care of in the specify method. |

306 | |

307 | There is no 'one perfect "specify"' for all purposes. This |

308 | routine should merely define a reasonably useful base |

309 | configuration of the MODEL. |

310 | |

311 | Other specify_whatElseYouWant methods can (should) also be |

312 | written. |

313 | |

314 | The name of a method is a communication tool. Please use |

315 | meaningful names as long as necessary to tell what the |

316 | method does. Avoid cryptic abbreviations and hyper- |

317 | specialized jargon known only to you and your three friends |

318 | when you are naming methods; however, do not shy away from |

319 | technical terms common to the engineering domain in which |

320 | you are modeling. |

321 | |

322 | } END NOTES; |

323 | |

324 | (* STOP {Error! Standard method "specify" called but not written in MODEL.}; *) |

325 | |

326 | END specify; |

327 | |

328 | METHOD reset; |

329 | NOTES 'purpose' SELF { |

330 | This method gets the MODEL to some standard starting state, |

331 | though not necessarily the most useful starting state for a |

332 | particular application. In Chem. Eng. terms, this method |

333 | establishes a base case. |

334 | |

335 | There is no 'one perfect "reset"' for all purposes. This |

336 | routine should merely define a reasonably useful base |

337 | configuration of the MODEL. |

338 | |

339 | Other reset_whatElseYouWant methods can (should) also be |

340 | written. |

341 | |

342 | Normally you do not need to write this method: your models |

343 | will inherit this one unless you override it (redefine it) |

344 | in your MODEL. |

345 | } |

346 | END NOTES; |

347 | |

348 | RUN ClearAll; |

349 | RUN specify; |

350 | |

351 | END reset; |

352 | |

353 | METHOD values; |

354 | END values; |

355 | |

356 | METHOD bound_self; |

357 | NOTES 'purpose' SELF { |

358 | Much of the art of nonlinear physical modeling is in |

359 | bounding the solution. |

360 | |

361 | This method should update the bounds on _locally_ defined |

362 | (IS_A) variables and IS_A defined MODEL parts. Updating |

363 | bounds requires some care. For example, the bounds on |

364 | fractions frequently don't need updating. |

365 | |

366 | A common formula for updating bounds is to define a region |

367 | around the current value of the variable. A linear region |

368 | size formula, as an example, would be: |

369 | |

370 | v.upper_bound := v + boundwidth * v.nominal; |

371 | v.lower_bound := v - boundwidth * v.nominal; |

372 | |

373 | Care must be taken that such a formula does not move the |

374 | bounds (particularly lower bounds) out so far as to allow |

375 | non-physical solutions. Logarithmic bounding regions are |

376 | also simple to calculate. |

377 | |

378 | Here boundwidth IS_A bound_width; |

379 | boundwidth is a real variable (but not a solver_var) or a |

380 | value you can use to determine how much "wiggle-room" you |

381 | want to give a solver. Small powers of 4 and 10 are usually |

382 | good values of boundwidth. |

383 | |

384 | Too small a boundwidth can cut off the portion of number |

385 | space where the solution is found. Too large a bound width |

386 | can allow solvers to wander for great distances in |

387 | uninteresting regions of the number space. |

388 | |

389 | This method should not bound variables passed into the |

390 | MODEL definition or parts passed into the definition. |

391 | } END NOTES; |

392 | |

393 | (* STOP {Error! Standard method "bound_self" called but not written in MODEL.}; *) |

394 | END bound_self; |

395 | |

396 | METHOD bound_all; |

397 | NOTES 'purpose' SELF { |

398 | This method should be like bound_self except that it bounds the |

399 | passed in variables and calls bound_self on the passed in parts. |

400 | It should then call bound_self. |

401 | } END NOTES; |

402 | |

403 | (* STOP {Error! Standard method "bound_all" called but not written in MODEL.}; *) |

404 | RUN bound_self; |

405 | END bound_all; |

406 | |

407 | METHOD scale_self; |

408 | NOTES 'purpose' SELF { |

409 | Most nonlinear (and many linear) models cannot be solved without |

410 | proper scaling of the variables. |

411 | |

412 | This method should reset the .nominal value on every real |

413 | variable in need of scaling. It should then call the |

414 | scale_self method on all the locally defined (IS_A) parts |

415 | of the MODEL. 0.0 is the worst possible nominal value. A |

416 | proper nominal is one such that you expect at the solution |

417 | the quantity |

418 | |

419 | abs(variable/(variable.nominal)) |

420 | |

421 | to be around 1 (in the range of [0.1..10] or [0.01..100]). |

422 | |

423 | Variables (like fractions) bounded such that they cannot be |

424 | too far away from 1.0 in magnitude probably don't need scaling |

425 | most of the time if they are also bounded away from 0.0. |

426 | |

427 | Some solvers, but not all, will attempt to scale the |

428 | equations and variables by heuristic matrix-based methods. |

429 | This works, but inconsistently; user-defined scaling is |

430 | generaly much superior. |

431 | |

432 | ASCEND makes it easy to do. You scale the variables, which |

433 | can only be done well by knowing something about where the |

434 | solution is going to be found (by being an engineer, for |

435 | example.) Then ASCEND can calculate an appropriate |

436 | equation-scaling by efficient symbolic methods. |

437 | |

438 | This method should not change the scaling of models and |

439 | variables that are received through the parameter list of |

440 | the MODEL. |

441 | } END NOTES; |

442 | |

443 | (* STOP {Error! Standard method "scale_self" called but not written in MODEL.}; *) |

444 | END scale_self; |

445 | |

446 | METHOD scale_all; |

447 | NOTES 'purpose' SELF { |

448 | This method should be like scale_self above except that it also |

449 | should scale the variables and models received through the |

450 | parameter list. It should then call scale_self to take care of |

451 | the local variables and models. |

452 | } END NOTES; |

453 | |

454 | (* STOP {Error! Standard method "scale_all" called but not written in MODEL.}; *) |

455 | RUN scale_self; |

456 | END scale_all; |

457 | END METHODS; |

458 | |

459 | MODEL cmumodel(); |

460 | NOTES |

461 | 'purpose' SELF { |

462 | This MODEL does nothing except provide a root |

463 | for a collection of loosely related models. |

464 | If it happens to reveal a few bugs in the software, |

465 | and perhaps masks others, well, what me worry? |

466 | BAA, 8/97. |

467 | } |

468 | 'methods' SELF { |

469 | This MODEL also provides a hook to put in candidates for |

470 | becoming ascBuiltin global methods. Global methods may be |

471 | overridden by local definitions. |

472 | BAA, 3/98. |

473 | } |

474 | END NOTES; |

475 | |

476 | END cmumodel; |

477 | |

478 | MODEL testcmumodel(); |

479 | (* |

480 | * All CMU test models, of whatever sort should ultimately be |

481 | * rooted here or be a final refinement of a reusable MODEL. |

482 | *) |

483 | METHODS |

484 | METHOD values; |

485 | (* |

486 | * In a final application MODEL, you should record at least one set of |

487 | * input values (values of the fixed variables and guesses of key |

488 | * solved-for variables) that leads to a good solution. |

489 | * Do this so noone need reinvent that set the next time |

490 | * you use the MODEL or someone picks the MODEL up after you. |

491 | *) |

492 | (* STOP {Error! Standard method "values" called but not written in MODEL.}; *) |

493 | END values; |

494 | |

495 | METHOD specify; |

496 | (* STOP {Error! Standard method "specify" called but not written in test MODEL.}; *) |

497 | END specify; |

498 | |

499 | METHOD ClearAll; |

500 | EXTERNAL asc_free_all_variables(SELF); |

501 | END ClearAll; |

502 | |

503 | METHOD reset; |

504 | (* This method gets the MODEL to some standard starting state, |

505 | * though not necessarily the most useful starting state for |

506 | * a particular application. In Chem. Eng. terms, this method |

507 | * establishes a base case. |

508 | * There is no 'one perfect "reset"' for all purposes. This |

509 | * routine should merely define a reasonably useful base configuration |

510 | * of the MODEL. |

511 | * Other reset_whatElseYouWant methods can (should) also be |

512 | * written. |

513 | * |

514 | * Normally you do not need to write this method: your models |

515 | * will inherit this one unless you override it (redefine it) |

516 | * in your MODEL. |

517 | *) |

518 | RUN ClearAll; |

519 | RUN specify; |

520 | END reset; |

521 | END testcmumodel; |

522 | |

523 | MODEL your_site_models(); |

524 | (* if you create a library to share with the net which is |

525 | * not just an end application of Carnegie Mellon models, |

526 | * please create an empy root MODEL such as this and use |

527 | * it as the origin of your library in the same way that |

528 | * we use cmumodel as the origin of our libraries. |

529 | * Thank you. |

530 | *) |

531 | END your_site_models; |

john.pye@anu.edu.au | ViewVC Help |

Powered by ViewVC 1.1.22 |