Parent Directory | Revision Log

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

*Mon Aug 2 01:05:11 2010 UTC*
(9 years, 11 months ago)
by *jpye*

File MIME type: text/x-ascend

File size: 19401 byte(s)

File MIME type: text/x-ascend

File size: 19401 byte(s)

Fix bug with 'RUN default', need to use Initialize(GetSimulationRoot(sim),...) for running methods!

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, write to the Free Software |

16 | Foundation, Inc., 59 Temple Place - Suite 330, |

17 | Boston, MA 02111-1307, USA. |

18 | *) |

19 | PROVIDE "basemodel.a4l"; |

20 | (* |

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

22 | |

23 | Basic definitions cmu libraries and standard methods. |

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

25 | in ASCEND IV. |

26 | *) |

27 | |

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

29 | (* This MODEL does nothing. |

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

31 | * |

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

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

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

35 | * syntax error. |

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

37 | * starting condition. |

38 | * |

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

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

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

42 | |

43 | @TODO document how this works |

44 | *) |

45 | END catch_Word_model; |

46 | |

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

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

49 | *) |

50 | ADD METHODS IN DEFINITION MODEL; |

51 | |

52 | METHOD ClearAll; |

53 | |

54 | NOTES 'purpose' SELF { |

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

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

57 | |

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

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

60 | default value. |

61 | } END NOTES; |

62 | |

63 | EXTERNAL asc_free_all_variables(SELF); |

64 | END ClearAll; |

65 | |

66 | (* |

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

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

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

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

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

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

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

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

75 | * |

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

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

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

79 | * writing mathematical modeling software in ways which |

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

81 | * |

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

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

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

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

86 | * |

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

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

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

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

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

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

93 | * |

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

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

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

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

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

99 | * end up calling one of them. |

100 | * |

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

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

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

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

105 | * |

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

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

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

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

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

111 | * |

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

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

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

115 | * as a self-contained simulation. |

116 | * |

117 | *) |

118 | |

119 | (* |

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

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

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

123 | *) |

124 | |

125 | METHOD check_self; |

126 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

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

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

135 | definition of success. |

136 | |

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

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

139 | checked. Usually there are redundant equations available |

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

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

142 | particularly tricky bits of the MODEL. |

143 | |

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

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

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

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

148 | |

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

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

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

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

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

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

155 | |

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

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

158 | may be bogus. |

159 | |

160 | Currently only STOP is implemented. |

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

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

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

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

165 | STOP does not crash the ASCEND system. |

166 | |

167 | } END NOTES; |

168 | |

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

170 | |

171 | END check_self; |

172 | |

173 | METHOD check_all; |

174 | |

175 | NOTES 'purpose' SELF { |

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

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

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

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

180 | stuff. |

181 | } END NOTES; |

182 | |

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

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

185 | |

186 | END check_all; |

187 | |

188 | METHOD defaults; |

189 | (* |

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

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

192 | *) |

193 | RUN default_self; |

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

195 | END defaults; |

196 | |

197 | METHOD on_load; |

198 | NOTES 'purpose' SELF { |

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

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

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

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

203 | } END NOTES; |

204 | RUN default_all; |

205 | END on_load; |

206 | |

207 | METHOD default; |

208 | NOTES 'purpose' SELF { |

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

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

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

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

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

214 | by the modeller. |

215 | } END NOTES; |

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

217 | (* nothing here *) |

218 | END default; |

219 | |

220 | METHOD default_self; |

221 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

228 | |

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

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

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

232 | are passed in through the parameter list. |

233 | |

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

235 | Define it anyway, leaving it empty. |

236 | |

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

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

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

240 | the PyGTK GUI. |

241 | } END NOTES; |

242 | EXTERNAL defaultself_visit_childatoms(SELF); |

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

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

245 | END default_self; |

246 | |

247 | METHOD default_all; |

248 | NOTES 'purpose' SELF { |

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

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

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

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

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

254 | appropriate default values to any variables received |

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

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

257 | declared default needs. |

258 | } END NOTES; |

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

260 | RUN default_self; |

261 | END default_all; |

262 | |

263 | METHOD specify; |

264 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

271 | * |

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

273 | * than simply counting equations and variables. |

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

275 | * |

276 | The general approach is to: |

277 | |

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

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

280 | |

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

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

283 | |

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

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

286 | |

287 | At all steps 1-3 |

288 | Pay special attention to indexed variables used in |

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

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

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

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

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

294 | correctly. |

295 | |

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

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

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

299 | statement to selectively TURN OFF the conflicting equations |

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

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

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

303 | which refers to that object are matched. |

304 | |

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

306 | are controlling conditions of WHEN and SWITCH statements |

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

308 | |

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

310 | routine should merely define a reasonably useful base |

311 | configuration of the MODEL. |

312 | |

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

314 | written. |

315 | |

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

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

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

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

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

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

322 | you are modeling. |

323 | |

324 | } END NOTES; |

325 | |

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

327 | |

328 | END specify; |

329 | |

330 | METHOD reset; |

331 | NOTES 'purpose' SELF { |

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

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

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

335 | establishes a base case. |

336 | |

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

338 | routine should merely define a reasonably useful base |

339 | configuration of the MODEL. |

340 | |

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

342 | written. |

343 | |

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

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

346 | in your MODEL. |

347 | } |

348 | END NOTES; |

349 | |

350 | RUN ClearAll; |

351 | RUN specify; |

352 | |

353 | END reset; |

354 | |

355 | METHOD values; |

356 | END values; |

357 | |

358 | METHOD bound_self; |

359 | NOTES 'purpose' SELF { |

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

361 | bounding the solution. |

362 | |

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

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

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

366 | fractions frequently don't need updating. |

367 | |

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

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

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

371 | |

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

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

374 | |

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

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

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

378 | also simple to calculate. |

379 | |

380 | Here boundwidth IS_A bound_width; |

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

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

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

384 | good values of boundwidth. |

385 | |

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

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

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

389 | uninteresting regions of the number space. |

390 | |

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

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

393 | } END NOTES; |

394 | |

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

396 | END bound_self; |

397 | |

398 | METHOD bound_all; |

399 | NOTES 'purpose' SELF { |

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

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

402 | It should then call bound_self. |

403 | } END NOTES; |

404 | |

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

406 | RUN bound_self; |

407 | END bound_all; |

408 | |

409 | METHOD scale_self; |

410 | NOTES 'purpose' SELF { |

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

412 | proper scaling of the variables. |

413 | |

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

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

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

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

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

419 | the quantity |

420 | |

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

422 | |

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

424 | |

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

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

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

428 | |

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

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

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

432 | generaly much superior. |

433 | |

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

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

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

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

438 | equation-scaling by efficient symbolic methods. |

439 | |

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

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

442 | the MODEL. |

443 | } END NOTES; |

444 | |

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

446 | END scale_self; |

447 | |

448 | METHOD scale_all; |

449 | NOTES 'purpose' SELF { |

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

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

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

453 | the local variables and models. |

454 | } END NOTES; |

455 | |

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

457 | RUN scale_self; |

458 | END scale_all; |

459 | END METHODS; |

460 | |

461 | MODEL cmumodel(); |

462 | NOTES |

463 | 'purpose' SELF { |

464 | This MODEL does nothing except provide a root |

465 | for a collection of loosely related models. |

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

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

468 | BAA, 8/97. |

469 | } |

470 | 'methods' SELF { |

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

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

473 | overridden by local definitions. |

474 | BAA, 3/98. |

475 | } |

476 | END NOTES; |

477 | |

478 | END cmumodel; |

479 | |

480 | MODEL testcmumodel(); |

481 | (* |

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

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

484 | *) |

485 | METHODS |

486 | METHOD values; |

487 | (* |

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

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

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

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

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

493 | *) |

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

495 | END values; |

496 | |

497 | METHOD specify; |

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

499 | END specify; |

500 | |

501 | METHOD ClearAll; |

502 | EXTERNAL asc_free_all_variables(SELF); |

503 | END ClearAll; |

504 | |

505 | METHOD reset; |

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

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

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

509 | * establishes a base case. |

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

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

512 | * of the MODEL. |

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

514 | * written. |

515 | * |

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

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

518 | * in your MODEL. |

519 | *) |

520 | RUN ClearAll; |

521 | RUN specify; |

522 | END reset; |

523 | END testcmumodel; |

524 | |

525 | MODEL your_site_models(); |

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

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

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

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

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

531 | * Thank you. |

532 | *) |

533 | END your_site_models; |

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

Powered by ViewVC 1.1.22 |