Guidelines for model-writing

From ASCEND
Jump to: navigation, search

This page will contain some guidelines for model-writing with ASCEND, specifically oriented towards the use of the newer PyGTK-based GUI. This supplements the more detailed material given in the users' manual (see the documentation page). Feel free to add any further comments/suggestions/advice here.

Object-oriented naming

Model names should be concise and represent things whereever possible, as opposed to processes or actions or calculations. So, for example, you might write a model car_dynamic rather than a model acceleration_and_braking.

Note that if you have a model file "mymodel.a4c", then if it contains a model named "mymodel", that model will by default be instantiated when the model file is loaded. This is handy in many cases, because normally a model file with have a 'main purpose' that you mostly open it for. So use this default naming to make your model file easier to use.

Variable naming

ASCEND is essentially a mathematical modelling language. As equations quickly become complex, it is important that variables are named in a way that makes the resulting equations readable. It is preferable, therefore, to use standard abbreviations and symbols like h (for enthalpy) wherever possible, rather than the more typical computer-science approach of specificEnthalpyOfTheThingWeAreInterestedIn.

Occasionally we come across cases where people from different backgrounds have different 'standard symbols'. In those cases, we tend to err towards the english/american standards from engineering textbooks. For energy systems modelling, textbooks like Holman, Cengel, and Moran & Shapiro give the general flavour.

Setting your parameters

The preferred way to set parameters in your model is to FIX them and then assign a value to them in a suitable METHOD. The quick-and-dirty way is to use an on_load method. A more sophisticated way is to use a specify method and a values methods. This makes reusing your model easier, because someone who wants to incorporate your model as a submodel in a larger problem can create an instance of your model then run the necessary methods on it, as part of their own model's methods.

Default values and initial guesses

It is recommended to write a default_self method in your model, which should be called from your on_load method. Any variables that need to be initialised to other than their internally-defined default value can then be assigned their. Note that these are not FIXed variables; these are variables that will be solved for, but when set to a good first guess, will solve much more readily, with less iterations.

Flowsheet modelling

Is is suggested, tentatively, that components in a flowsheet be given short abbreviated names in two or three capital letters, suffixed with a number if necessary, eg TU1 for Turbine 1, or PU2 for Pump 2. These short names are usually sufficiently memorable, but succinct enough to keep your model readable without excessive typing.

Use of parametric models

In ASCEND, it is possible to write models that require parameters in order to be instantiated. With our canvas-based modeller, we have currently found some difficulty in making use of such models, because of the difficulty that arises with the use of ARE_THE_SAME to merge variables in such cases. So for reusable block models, we are currently preferring the use of non-parametric models, although that might change in the future.

Model testing

It is advisable when writing models to also develop simple 'test models' that instantiate the model you have just written, and set its parameters for a typical set of conditions. This model should solve easily, and should contain a self_test METHOD that includes various ASSERT statements to check that solved variables have the expected values. This aids greatly in debugging and maintaining models for future use.

on_load behaviour

Ideally, when a model file is loaded with the PyGTK GUI, it should immediately put itself into a solvable state. One should be able to load a model, click 'solve' and have some useful results. The power comes next, when the user can manually tweak the values of any variables in the model, to obtain results for new/different problems.

Avoid magic numbers

In general, your equations should not contain an 'magic numbers'. This means values for which the source or meaning is not clear and not explained. Such numbers make model files harder to maintain, as future user's won't know how to check whether a given value is correct, or what it means, or where it comes from. Normally, such 'magic numbers' should be defined as suitably-named constants, using a couple of possible approaches.

For widely-used constants, such as \pi = 3.14159265358 or g = 9.81 m/s², you can use predefined values 1{PI} and 1{EARTH_G}, which are mostly defined in models/measures.a4l. This makes your model more readable; the intention is clear, and ASCEND looks after the units for you as a bonus.

For constants that are important only in the context of a particular model, you can use types that are refinements of real_constant (declared using the CONSTANT statement), and then define your value in the model like this:

(* critical point temperature for water *)
T_c IS_A temperature_constant;
T_c :== 647.096 {K};

The above approach is also useful for defining design parameters: they might be constant in the context of the problem that ASCEND is solving, but you might want to try running your model with different values to see what happens. In that case, you can change the values and re-run the model.

One fair exception to the above 'rule' is that if you are citing an equation from a publication, and the equation is given in correct units-free form, then the dimensionless constants from that equation can be preserved in the ASCEND code. This applies, for example to many heat-transfer correlations, such as the Dittus-Boelter correlation], for example:

n "index of Pr in Dittus-Boelter equation" IS_A real_constant;
n :== 0.4 (* 0.4 for heating of the fluid, 0.3 for cooling *)
(* Dittus-Boelter equation *)
Nu = 0.023 * Re^(4./5) * Pr^n;

Indenting

The suggested indenting style for ASCEND is as follows:

MODEL mymodel;
    p IS_A pressure;
    T IS_A temperature;
    n IS_A mole;
    V IS_A volume;

    p*V = n * 1{GAS_C} * T;
METHODS
METHOD on_load;
    FIX p, T;
    p := 1 {bar};
    T := 300 {K};
END on_load;
END mymodel;

Although you might be tempted to indent the METHODS and METHOD sections, it is our view that that leads to excessive indentation, without hugely increasing readability. If you use our syntax highlighting add-ins for various editors, the above syntax is usually quite readable.

Document your equations

When writing models, it is a huge boost in re-usability if your model equations are clearly cited/sourced. The best way to do this is in comments near the equation, for example:

(* Following 3 eqns are from Potter & Wiggert, 3rd SI edition, sects 9.1, 9.2 and 9.4.*)
S2.M^2 = ( S1.M^2 + 2/(k-1) ) / (2*k/(k-1)*S1.M^2 - 1);

S2.p / S1.p = 2*k/(k+1)*S1.M^2 - (k-1)/(k+1);

S2.T / S1.T = ( 1 + (k-1)/2*S1.M^2) * (2*k/(k-1)*S1.M^2 - 1)/ ((k+1)^2/2/(k-1)*S1.M^2);