Skip to content
Michael Wetter edited this page Mar 10, 2015 · 8 revisions

Introduction

This page provides a check list that should be used when contributing a new class (model, block, function etc.) to the library.

General

  1. Follow the conventions in Annex60.UsersGuide.Conventions. (This link will be replaced with a link to the Annex library when the first html version is posted.)
  2. Partial classes and base classes that are not of interest to the user should be stored in a subdirectory called BaseClasses.
  3. Examples and validation models should be in directories such as Valves.Examples and Valves.Validations. A script for the regression tests must be added as described below.
  4. Do not copy sections of code. Use object inheritance.
  5. Implement components of fluid flow systems by extending the partial classes in Annex60.Fluid.Interfaces.
  6. Use the full package names when instantiating a class.

Type Declarations

  1. Declare variables and final parameters that are not of interest to users as protected.

  2. Set default parameter values as follows:

    1. If a parameter value can range over a large region, do not provide a default value. Examples are nominal mass flow rates.

    2. If a parameter value does not vary significantly, provide a default by using its start attribute. For example, use

      parameter Real eps(start=0.8, min=0, max=1, unit="1")
        "Heat exchanger effectiveness";
    3. If a parameter value can be precomputed based on other parameters, set its default value to this equation. For example,

      parameter Medium.MassFlowRate m_flow_small(min=0) = 1E-4*m_flow_nominal
      ...
    4. If a parameter value should not be changed by a user, use the final keyword.

  3. For parameters and variables, provide values for the min and max attribute where applicable.

  4. For any variable or parameter that may need to be solved numerically, provide a value for the start and nominal attribute.

  5. Use types from Modelica.SIunits where possible.

Equations and Algorithms

  1. Avoid events where possible.

  2. Only divide by quantities that cannot take on zero. For example, if x may take on zero, use y=x, not 1=y/x, as the second version indicates to a simulator that it is save to divide by x.

  3. Use SI units in all equations.

  4. Use the assert function to check for invalid values of parameters or variables. For example, use assert(phi>=0, "Relative humidity must not be negative.")

  5. Use either graphical modeling or textual code. Avoid using both within one class.

  6. For computational efficiency, equations shall were possible be differentiable and have a continuous first derivative.

  7. Avoid equations where the first derivative with respect to another variable is zero, except at a single point. For example, if x, y are variables, and x = f(y), avoid y = 0 for x<0 and y=x^2 otherwise. The reason is that if a simulator tries to solve 0=f(x), then any value of x <= 0 is a solution, which can cause instability in the solver.

  8. Do not replace an equation by a constant for a single value, unless the derivative of the original equation is zero for this value. For example, if computing a pressure drop dp may involve computing a long equation, but one knows that the result is always zero if the volume flow rate V_flow is zero, one may be inclined to use a construct of the form dp = smooth(1, if V_flow == 0 then 0 else f(V_flow)); The problem with this formulation is that for V_flow=0, the derivative is dp/dV_flow = 0. However, the limit dp/dV_flow, as |V_flow| tends to zero, may be non-zero. Hence, the first derivative has a discontinuity at V_flow=0, which can cause a solver to fail to solve the equation because the smooth statement declared that the first derivative exists and is continuous.

  9. Make sure that the derivatives of equations are bounded on compact sets. For example, instead of using y=sign(x) * sqrt(abs(x)), approximate the equation with a differentiable function that has a finite derivative near zero. Use functions form Annex60.Utilities.Math for this approximation.

  10. Whenever possible, a Modelica tool should not have to do numerical differentiation. For example, in Dymola, if your model translation log shows

    Number of numerical Jacobians: 1
    

    (or any number other than zero), then enter on the command line

    Hidden.PrintFailureToDifferentiate = true;
    

    Next, translate the model again to see what functions cannot be differentiated symbolically. Then, implement symbolic derivatives for this function. See implementation of function derivatives.

Functions

  1. Use the smoothOrder annotation if a function is differentiable.
  2. If a function is invertible, also implement its inverse function and use the inverse attribute. See Annex60.Fluid.BaseClasses.FlowModels for an example.
  3. If a model allows a linearized implementation of an equation, then implement the linearized equation in an equation section and not in the algorithm section of a function. Otherwise, a symbolic processor cannot invert the linear equation, which can lead to coupled systems of equations. See Annex60.Fluid.BaseClasses.FlowModels for an example.

Package order

  1. Packages are first sorted alphabetically by the function _sort_package_order. That function is part of BuildingsPy and is called by

    import buildingspy.development.refactor as r
    r.write_package_order(".", True)
  2. After alphabetical sorting, the following packages, if they exist, are moved to the front:

    Tutorial
    UsersGuide

    and the following packages, if they exist, are moved to the end:

    Data
    Types
    Examples
    Validation
    Benchmarks
    Experimental
    Interfaces
    BaseClasses
    Internal
    Obsolete

    The remaining classes are ordered as follows and inserted between the above list: First, models, blocks and records are listed, then functions, and then packages.

Documentation

  1. Add a one-line comment to all parameters and variables, including protected ones.

  2. Group similar variables using the group and tab annotation. For example, use

    parameter Modelica.SIunits.Time tau = 60
      "Time constant at nominal flow"
      annotation (Dialog(group="Nominal condition"));

    or use

    parameter Types.Dynamics substanceDynamics=energyDynamics
      "Formulation of substance balance"
      annotation(Evaluate=true, Dialog(tab = "Assumptions", group="Dynamics"));
  3. Add model documentation to the info section. To document equations, use the format

    <p>
    The polynomial has the form
    </p>
    <p align="center" style="font-style:italic;">
    y = a<sub>1</sub> + a<sub>2</sub> x + a<sub>3</sub> x<sup>2</sup> + ...,
    </p>
    <p>
    where <i>a<sub>1</sub></i> is ...

    To denote time derivatives, such as for mass flow rate, use <code>m&#775;</code>.

    To refer to parameters of the model, use the format

    To linearize the equation, set <code>linearize=true</code>.

    To format tables, use

    <p>
    <table summary="summary" border="1" cellspacing="0" cellpadding="2" style="border-collapse:collapse;">
    <tr><th>Header 1</th>       <th>Header 2</th>     </tr>
    <tr><td>Data 1</td>         <td>Data 2</td>       </tr>
    </table>
    </p>

    To include figures, place the figure into a directory in Annex60/Resources/Images/ that has the same name as the full package. For example, use

    </p>
    <p align="center">
    <img alt="Image of ..."
    src="modelica://Annex60/Resources/Images/Fluid/FixedResistances/FixedResistanceDpM.png"/>
    </p>
    <p>

    To create new figures, put the source file for the figure, preferably in svg format, in the same directory as the png file. svg files can be created with http://inkscape.org/, which works on any operating system. See for example the file in Resources/Images/Examples/Tutorial/SpaceCooling/schematics.svg.

  4. Add author information to the revision section.

  5. Run a spell check.

  6. Start headings with <h4>.

  7. Add hyperlinks to other models using their full name. For example, use

    See <a href="modelica://Annex60.Fluid.Sensors.Density"> Annex60.Fluid.Sensors.Density</a>.

  8. To refer to names of parameters or variables in the documentation and revision sections, use the syntax <code>...</code>. Do not use <tt>...</tt>.

  9. Add a default component name, such as

    annotation(defaultComponentName="senDen", ...
  10. Keep the line length to no more than around 80 characters.

  11. For complex packages, provide a User's Guide, and reference the User's Guide in Annex60.UsersGuide.

  12. If anything still needs to be revised, add the string fixme with a descriptive comment. Prior to a library release, the library will be searched for this string to avoid releasing unfinished code.

  13. A suggested template for the documentation of classes is below. Except for the short introduction, the sections are optional.

    <p>
    A short introduction.
    </p>
    <h4>Main equations</h4>
    <p>
    xxx
    </p>
    <h4>Assumption and limitations</h4>
    <p>
    xxx
    </p>
    <h4>Typical use and important parameters</h4>
    <p>
    xxx
    </p>
    <h4>Options</h4>
    <p>
    xxx
    </p>
    <h4>Validation</h4>
    <p>
    Describe whether the validation was done using
    analytical validation, comparative model validation
    or empirical validation.
    </p>
    <h4>Implementation</h4>
    <p>
    xxx
    </p>
    <h4>References</h4>
    <p>
    xxx
    </p>

Unit Tests

  1. Implement at least one unit test for each class and run the unit tests. See unit test implementation.
  2. Use Annex60.Utilities.Diagnostics.AssertEquality to cause a test to fail if the result is incorrect.
  3. Ensure that no unit test requires a numerical Jacobian. If a numerical Jacobian is needed, improve the model.
Clone this wiki locally