Skip to content
Michael Wetter edited this page Jul 27, 2020 · 13 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 IBPSA.UsersGuide.Conventions. (This link will be replaced with a link to the IBPSA library when the first html version is posted.)
  2. Classes declared as partial and base classes that are not of interest to the user should be stored in a subdirectory called BaseClasses. Each other class, except for constants, must have an icon.
  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 classes in IBPSA.Fluid.Interfaces.
  6. Use the full package names when instantiating a class.
  7. Models, functions and blocks must be implemented as one model, function or block per file. An exception are the IBPSA.Media packages.

Type Declarations

  1. Declare all public parameters before protected ones.

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

  3. 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 but need to be verified by the user, provide a default value by using its start attribute. For example, for a heat exchanger, use

      parameter Real eps(start=0.8, min=0, max=1, unit="1")
        "Heat exchanger effectiveness";

      Do not use parameter Real eps=0.8 as this can lead to errors that are difficult to detect if a modeller forgets to overwrite the default value of 0.8 with the actual value. The model will simulate, but gives wrong results due to unsuited parameter values and there will be no warning. On the other hand, using parameter Real eps(start=0.8) will give a warning and hence users can assign better values.

    3. If a parameter value can be precomputed based on other parameters, set its value to this equation. For example,

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

  4. For parameters and variables, provide values for the min and max attribute where applicable. Be aware, that these bounds are not enforced by the simulator. If the min and max attribute are set, each violation of these bounds during the simulation may raise a warning.

    Simulators may allow to supress these warnings. In Dymola, violation of bounds can be checked using

    Advanced.AssertAllInsideMinMax=true;
    
  5. For any variable or parameter that may need to be solved numerically, provide a value for the start and nominal attribute.

  6. 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 the assert function together with "In " + getInstanceName() + ":... to check for invalid values of parameters or variables. For example, use

    assert(phi>=0, "In " + getInstanceName() + ": Relative humidity must not be negative.");

    Note the use of getInstanceName(), which will write the instance name as part of the error message. Otherwise, JModelica will not write the instance name.

  4. Use either graphical modeling or textual code. When using graphical schematic modeling, do not add textual equations. For example, avoid the following, as on the graphical editor, the model looks appears to be singular:

    model Avoid
      Modelica.Blocks.Continuous.Integrator integrator "Integrator"
        annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
      equation
      integrator.u = 1;
    end Avoid;
  5. For computational efficiency, equations shall where possible be differentiable and have a continuous first derivative.

  6. Avoid equations where the first derivative with respect to another variable is zero. 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. Note that this problem do not exist for functions that assign a value to a constant as these will be evaluated during the model translation.

  7. 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.

  8. 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 IBPSA.Utilities.Math for this approximation.

  9. 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

    Advanced.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 annotation. See IBPSA.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 IBPSA.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 description string 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 IBPSA/Resources/Images/ that has the same name as the full package. For example, use

    </p>
    <p align="center">
    <img alt="Image of ..."
    src="modelica://IBPSA/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://IBPSA.Fluid.Sensors.Density"> IBPSA.Fluid.Sensors.Density</a>.

  8. Add a default component name, such as

    annotation(defaultComponentName="senDen", ...

    to objects that will be used as drag and drop elements, as this automatically assigns them this name.

  9. Keep the line length to no more than around 80 characters.

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

  11. Use the string fixme within development branches to mark passages that still need to be revised (e.g., to improve code or to fix bugs). Before merging a branch into the master, all fixme strings must be removed. Within the master branch, no fixme are allowed.

  12. 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>Dynamics</h4>
    <p>
    Describe which states and dynamics are present in the model
    and which parameters may be used to influence them.
    This need not be added in partial classes.
    </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>
  13. Always use lower case html tags.

Unit Tests

  1. Implement at least one unit test for each model, block and function, and run the unit tests. Unit tests should cover all branches of if-then constructs. See unit test implementation.
  2. Use IBPSA.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.