Parent Directory | Revision Log

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

*Mon Feb 26 04:54:45 2007 UTC*
(17 years, 5 months ago)
by *johnpye*

File MIME type: text/x-ascend

File size: 19645 byte(s)

File MIME type: text/x-ascend

File size: 19645 byte(s)

Added new 'default' functionality plus test case

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 on_load; |

216 | NOTES 'purpose' SELF { |

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

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

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

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

221 | } END NOTES; |

222 | RUN reset; |

223 | RUN default_all; |

224 | END on_load; |

225 | |

226 | METHOD default; |

227 | NOTES 'purpose' SELF { |

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

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

230 | 'default_self' methods for most MODELs. It should be superiour, since using |

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

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

233 | by the modeller. |

234 | } END NOTES; |

235 | (* nothing here *) |

236 | END default; |

237 | |

238 | METHOD default_self; |

239 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

246 | |

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

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

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

250 | are passed in through the parameter list. |

251 | |

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

253 | Define it anyway, leaving it empty. |

254 | |

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

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

257 | compiler. |

258 | } END NOTES; |

259 | EXTERNAL asc_default_self(SELF); |

260 | RUN default; |

261 | END default_self; |

262 | |

263 | METHOD default_all; |

264 | |

265 | NOTES 'purpose' SELF { |

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

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

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

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

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

271 | appropriate default values to any variables received |

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

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

274 | declared default needs. |

275 | } END NOTES; |

276 | RUN default_self; |

277 | END default_all; |

278 | |

279 | METHOD specify; |

280 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

287 | * |

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

289 | * than simply counting equations and variables. |

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

291 | * |

292 | The general approach is to: |

293 | |

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

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

296 | |

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

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

299 | |

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

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

302 | |

303 | At all steps 1-3 |

304 | Pay special attention to indexed variables used in |

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

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

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

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

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

310 | correctly. |

311 | |

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

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

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

315 | statement to selectively TURN OFF the conflicting equations |

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

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

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

319 | which refers to that object are matched. |

320 | |

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

322 | are controlling conditions of WHEN and SWITCH statements |

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

324 | |

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

326 | routine should merely define a reasonably useful base |

327 | configuration of the MODEL. |

328 | |

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

330 | written. |

331 | |

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

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

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

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

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

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

338 | you are modeling. |

339 | |

340 | } END NOTES; |

341 | |

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

343 | |

344 | END specify; |

345 | |

346 | METHOD reset; |

347 | NOTES 'purpose' SELF { |

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

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

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

351 | establishes a base case. |

352 | |

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

354 | routine should merely define a reasonably useful base |

355 | configuration of the MODEL. |

356 | |

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

358 | written. |

359 | |

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

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

362 | in your MODEL. |

363 | } |

364 | END NOTES; |

365 | |

366 | RUN ClearAll; |

367 | RUN specify; |

368 | |

369 | END reset; |

370 | |

371 | METHOD bound_self; |

372 | NOTES 'purpose' SELF { |

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

374 | bounding the solution. |

375 | |

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

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

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

379 | fractions frequently don't need updating. |

380 | |

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

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

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

384 | |

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

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

387 | |

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

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

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

391 | also simple to calculate. |

392 | |

393 | Here boundwidth IS_A bound_width; |

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

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

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

397 | good values of boundwidth. |

398 | |

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

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

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

402 | uninteresting regions of the number space. |

403 | |

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

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

406 | } END NOTES; |

407 | |

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

409 | END bound_self; |

410 | |

411 | METHOD bound_all; |

412 | NOTES 'purpose' SELF { |

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

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

415 | It should then call bound_self. |

416 | } END NOTES; |

417 | |

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

419 | RUN bound_self; |

420 | END bound_all; |

421 | |

422 | METHOD scale_self; |

423 | NOTES 'purpose' SELF { |

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

425 | proper scaling of the variables. |

426 | |

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

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

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

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

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

432 | the quantity |

433 | |

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

435 | |

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

437 | |

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

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

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

441 | |

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

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

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

445 | generaly much superior. |

446 | |

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

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

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

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

451 | equation-scaling by efficient symbolic methods. |

452 | |

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

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

455 | the MODEL. |

456 | } END NOTES; |

457 | |

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

459 | END scale_self; |

460 | |

461 | METHOD scale_all; |

462 | NOTES 'purpose' SELF { |

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

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

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

466 | the local variables and models. |

467 | } END NOTES; |

468 | |

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

470 | RUN scale_self; |

471 | END scale_all; |

472 | END METHODS; |

473 | |

474 | MODEL cmumodel(); |

475 | NOTES |

476 | 'purpose' SELF { |

477 | This MODEL does nothing except provide a root |

478 | for a collection of loosely related models. |

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

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

481 | BAA, 8/97. |

482 | } |

483 | 'methods' SELF { |

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

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

486 | overridden by local definitions. |

487 | BAA, 3/98. |

488 | } |

489 | END NOTES; |

490 | |

491 | END cmumodel; |

492 | |

493 | MODEL testcmumodel(); |

494 | (* |

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

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

497 | *) |

498 | METHODS |

499 | METHOD values; |

500 | (* |

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

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

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

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

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

506 | *) |

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

508 | END values; |

509 | |

510 | METHOD specify; |

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

512 | END specify; |

513 | (* |

514 | METHOD ClearAll; |

515 | EXTERNAL asc_free_all_variables(SELF); |

516 | END ClearAll; |

517 | |

518 | METHOD reset; |

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

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

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

522 | * establishes a base case. |

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

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

525 | * of the MODEL. |

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

527 | * written. |

528 | * |

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

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

531 | * in your MODEL. |

532 | *) |

533 | RUN ClearAll; |

534 | RUN specify; |

535 | END reset; |

536 | *) |

537 | END testcmumodel; |

538 | |

539 | MODEL your_site_models(); |

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

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

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

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

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

545 | * Thank you. |

546 | *) |

547 | END your_site_models; |

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

Powered by ViewVC 1.1.22 |