Parent Directory | Revision Log

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

*Wed Jun 21 07:00:45 2006 UTC*
(17 years, 11 months ago)
by *johnpye*

File MIME type: text/x-ascend

File size: 19211 byte(s)

File MIME type: text/x-ascend

File size: 19211 byte(s)

Merged changes from DAE branch (revisions 702 to 819) back into trunk. This adds the Integration API to the ASCEND solver (in base/generic). Also provides pre-alpha support for 'IDA' from the SUNDIALS suite, a DAE solver. Many other minor code clean-ups, including adoption of new 'ASC_NEW' and friends (to replace 'ascmalloc') Added some very sketchy stuff providing 'DIFF(...)' syntax, although it is anticipated that this will be removed.

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

223 | END on_load; |

224 | |

225 | METHOD default_self; |

226 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

233 | |

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

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

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

237 | are passed in through the parameter list. |

238 | |

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

240 | Define it anyway, leaving it empty. |

241 | |

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

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

244 | compiler. |

245 | } END NOTES; |

246 | |

247 | STOP {Error! Standard method "default_self" called but not written in MODEL.}; |

248 | END default_self; |

249 | |

250 | METHOD default_all; |

251 | |

252 | NOTES 'purpose' SELF { |

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

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

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

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

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

258 | appropriate default values to any variables received |

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

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

261 | declared default needs. |

262 | } END NOTES; |

263 | |

264 | STOP {Error! Standard method "default_all" called but not written in MODEL.}; |

265 | RUN default_self; |

266 | END default_all; |

267 | |

268 | METHOD specify; |

269 | NOTES 'purpose' SELF { |

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

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

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

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

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

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

276 | * |

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

278 | * than simply counting equations and variables. |

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

280 | * |

281 | The general approach is to: |

282 | |

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

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

285 | |

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

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

288 | |

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

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

291 | |

292 | At all steps 1-3 |

293 | Pay special attention to indexed variables used in |

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

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

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

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

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

299 | correctly. |

300 | |

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

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

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

304 | statement to selectively TURN OFF the conflicting equations |

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

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

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

308 | which refers to that object are matched. |

309 | |

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

311 | are controlling conditions of WHEN and SWITCH statements |

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

313 | |

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

315 | routine should merely define a reasonably useful base |

316 | configuration of the MODEL. |

317 | |

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

319 | written. |

320 | |

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

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

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

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

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

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

327 | you are modeling. |

328 | |

329 | } END NOTES; |

330 | |

331 | STOP {Error! Standard method "specify" called but not written in MODEL.}; |

332 | |

333 | END specify; |

334 | |

335 | METHOD reset; |

336 | NOTES 'purpose' SELF { |

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

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

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

340 | establishes a base case. |

341 | |

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

343 | routine should merely define a reasonably useful base |

344 | configuration of the MODEL. |

345 | |

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

347 | written. |

348 | |

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

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

351 | in your MODEL. |

352 | } |

353 | END NOTES; |

354 | |

355 | RUN ClearAll; |

356 | RUN specify; |

357 | |

358 | END reset; |

359 | |

360 | METHOD bound_self; |

361 | NOTES 'purpose' SELF { |

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

363 | bounding the solution. |

364 | |

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

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

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

368 | fractions frequently don't need updating. |

369 | |

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

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

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

373 | |

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

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

376 | |

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

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

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

380 | also simple to calculate. |

381 | |

382 | Here boundwidth IS_A bound_width; |

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

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

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

386 | good values of boundwidth. |

387 | |

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

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

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

391 | uninteresting regions of the number space. |

392 | |

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

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

395 | } END NOTES; |

396 | |

397 | STOP {Error! Standard method "bound_self" called but not written in MODEL.}; |

398 | END bound_self; |

399 | |

400 | METHOD bound_all; |

401 | NOTES 'purpose' SELF { |

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

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

404 | It should then call bound_self. |

405 | } END NOTES; |

406 | |

407 | STOP {Error! Standard method "bound_all" called but not written in MODEL.}; |

408 | RUN bound_self; |

409 | END bound_all; |

410 | |

411 | METHOD scale_self; |

412 | NOTES 'purpose' SELF { |

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

414 | proper scaling of the variables. |

415 | |

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

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

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

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

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

421 | the quantity |

422 | |

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

424 | |

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

426 | |

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

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

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

430 | |

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

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

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

434 | generaly much superior. |

435 | |

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

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

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

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

440 | equation-scaling by efficient symbolic methods. |

441 | |

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

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

444 | the MODEL. |

445 | } END NOTES; |

446 | |

447 | STOP {Error! Standard method "scale_self" called but not written in MODEL.}; |

448 | END scale_self; |

449 | |

450 | METHOD scale_all; |

451 | NOTES 'purpose' SELF { |

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

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

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

455 | the local variables and models. |

456 | } END NOTES; |

457 | |

458 | STOP {Error! Standard method "scale_all" called but not written in MODEL.}; |

459 | RUN scale_self; |

460 | END scale_all; |

461 | END METHODS; |

462 | |

463 | MODEL cmumodel(); |

464 | NOTES |

465 | 'purpose' SELF { |

466 | This MODEL does nothing except provide a root |

467 | for a collection of loosely related models. |

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

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

470 | BAA, 8/97. |

471 | } |

472 | 'methods' SELF { |

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

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

475 | overridden by local definitions. |

476 | BAA, 3/98. |

477 | } |

478 | END NOTES; |

479 | |

480 | END cmumodel; |

481 | |

482 | MODEL testcmumodel(); |

483 | (* |

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

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

486 | *) |

487 | METHODS |

488 | METHOD values; |

489 | (* |

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

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

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

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

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

495 | *) |

496 | STOP {Error! Standard method "values" called but not written in MODEL.}; |

497 | END values; |

498 | |

499 | METHOD specify; |

500 | STOP {Error! Standard method "specify" called but not written in test MODEL.}; |

501 | END specify; |

502 | (* |

503 | METHOD ClearAll; |

504 | EXTERNAL asc_free_all_variables(SELF); |

505 | END ClearAll; |

506 | |

507 | METHOD reset; |

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

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

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

511 | * establishes a base case. |

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

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

514 | * of the MODEL. |

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

516 | * written. |

517 | * |

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

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

520 | * in your MODEL. |

521 | *) |

522 | RUN ClearAll; |

523 | RUN specify; |

524 | END reset; |

525 | *) |

526 | END testcmumodel; |

527 | |

528 | MODEL your_site_models(); |

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

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

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

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

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

534 | * Thank you. |

535 | *) |

536 | END your_site_models; |

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

Powered by ViewVC 1.1.22 |