Parent Directory | Revision Log

Revision **1290** -
(**hide 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 | aw0a | 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 | johnpye | 1290 | (* STOP {Error! Standard method "check_self" called but not written in MODEL.}; *) |

188 | aw0a | 1 | |

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 | johnpye | 1290 | (* STOP {Error! Standard method "check_all" called but not written in MODEL.}; *) |

202 | aw0a | 1 | 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 | johnpye | 669 | 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 | johnpye | 1290 | RUN reset; |

223 | RUN default_all; | ||

224 | johnpye | 669 | END on_load; |

225 | |||

226 | johnpye | 1290 | 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 | aw0a | 1 | 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 | johnpye | 1290 | EXTERNAL asc_default_self(SELF); |

260 | RUN default; | ||

261 | aw0a | 1 | 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 | johnpye | 1290 | (* STOP {Error! Standard method "specify" called but not written in MODEL.}; *) |

343 | aw0a | 1 | |

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 | johnpye | 1290 | (* STOP {Error! Standard method "bound_self" called but not written in MODEL.}; *) |

409 | aw0a | 1 | 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 | johnpye | 1290 | (* STOP {Error! Standard method "bound_all" called but not written in MODEL.}; *) |

419 | aw0a | 1 | 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 | johnpye | 1290 | (* STOP {Error! Standard method "scale_self" called but not written in MODEL.}; *) |

459 | aw0a | 1 | 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 | johnpye | 1290 | (* STOP {Error! Standard method "scale_all" called but not written in MODEL.}; *) |

470 | aw0a | 1 | 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 | johnpye | 1290 | (* STOP {Error! Standard method "values" called but not written in MODEL.}; *) |

508 | aw0a | 1 | END values; |

509 | |||

510 | METHOD specify; | ||

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

512 | aw0a | 1 | 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 |