HYBRID Code Standards - idaholab/HYBRID GitHub Wiki
A large portion of the Hybrid Repository is Modelica models. Therefore Modelica Code Standards are required.
This page provides a checklist that should be used when contributing a new class (model, block, connector, function, package, etc.) to the libraries that comprise NHES models.
- Follow the conventions of the Modelica Standard Library (MSL), which are as follows:
Note, in the html documentation of any Modelica library, the headings "h1, h2, h3" should not be used. These headings are reserved for the automatically generated documentation and headings. Additional headings in the html documentation should start with "h4."
In the Modelica package, the following conventions are used:
-
Comments and annotations always start with a capital letter, e.g.,
<!-- language-all: lang-none --> parameter Real a = 1 "Arbitrary factor";
-
Class and instance names are usually written in upper and lower case letters, e.g., "ElectricCurrent". An underscore is only used at the end of a name to characterize a lower or upper index, e.g., "pin_a" may be rendered as “pina”.
-
Class names always start with an upper case letter.
-
Instance names, i.e., names of component instances and variables (with the exception of constants), usually start with a lower case letter with only a few exceptions based on common terminology (such as "T" for a temperature variable).
-
Constant names, i.e., names of variables declared with the "constant" prefix, follow the usual naming conventions (upper and lower case letters) and usually start with an upper case letter, e.g. UniformGravity, SteadyState.
-
The two connectors of a domain that have identical declarations and different icons are usually distinguished by "_a", "_b" or "_p", "_n", e.g., Flange_a/Flange_b, HeatPort_a, HeatPort_b.
-
The instance name of a component is always displayed in its icon (= text string "%name") in blue color. A connector class has the instance name definition in the diagram layer and not in the icon layer. Parameter values, e.g., resistance, mass, gear ratio, are displayed in the icon in black color in a smaller font size than the instance name.
-
A connector class has the instance name definition in the diagram layer and not in the icon layer.
-
A main package usually has the following subpackages:
- UsersGuide, containing an overall description of the library and how to use it.
- Examples, containing models demonstrating the usage of the library.
- Interfaces, containing connectors and partial models.
- Types, containing type, enumeration, and selected definitions.
- BaseClasses, containing models, partial models, etc. that are not of interest to the user.
In addition to the MSL conventions, the following conventions are used:
-
Names of models, blocks and packages should start with an upper-case letter and be a noun or a noun with a combination of adjectives and nouns. Use camel-case notation to combine multiple words, such as
HeatTransfer
. -
Parameter and variables names are usually a character, such as
T
for temperature andp
for pressure, or a combination of the first three characters of a word, such ashigPreSetPoi
for “high pressure set point”. -
Comments should be added to each class (package, model, function, etc.). The first character should be an upper case letter.
-
Where applicable, all variables, including protected variables, must have units.
- All classes, with the exception of models within
BaseClasses
and constants, must have icons. - Examples, i.e., regression tests, should be in a directory such as
Electrolysis.Examples
. - Do not copy sections of code. Use object inheritance.
- Declare all public parameters before protected ones.
- Declare variables and final parameters that are not of interest to users as protected.
- Set default parameter values as follows:
-
If a parameter value can range over a large region, do not provide a default value. Examples are nominal mass flow rates.
-
If a parameter value does not vary significantly but needs to be verified by the user, provide a default value by using its starting 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(unit="1") "Heat exchanger effectiveness";
as this can lead to errors that are difficult to detect if a modeler 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.
-
If a parameter value can be precomputed based on other parameters, set its value to the appropriate equation. For example,
Parameter Medium.MassFlowRate m_flow_small(min=0) = 1E-4*m_flow_nominal;
-
If a parameter value should not be changed by a user, use the
final
keyword. For example, usefinal parameter Modelica.SIunits.Frequency fn=60 "Nominal frequency";
-
For parameters and variables, provide values for the min and max attributes where applicable. Be aware that these bounds are not enforced by the simulator. If the min and max attributes are set, each violation of these bounds during the simulation may raise a warning.
Compilers may allow suppression of these warnings. In Dymola, violation of bounds can be checked usingAdvanced.AssertAllInsideMinMax=true;
-
For any variable or parameter that may need to be solved numerically, provide a value for the
start
andnominal
attribute. -
Use types from
Modelica.SIunits
where possible.
- Avoid events (i.e., discrete behaviors that are generated by conditional expressions) where possible.
- If possible, only divide by quantities that cannot be zero. For example, if x may equal zero, use
y=x
, not1=y/x
, as the latter version indicates to a simulator that it is safe to divide by x. - Use the
assert
function to check for invalid values of parameters or variables. For example, useassert(phi>=0, "Relative humidity must not be negative.")
. - For computational efficiency, equations shall, were possible, be differentiable and have a continuous first derivative.
- Avoid equations where the first derivative with respect to another variable is zero. For example, if
x, y
are variables, andx = f(y)
, avoidy = 0
forx<0
andy=x^2
otherwise. The reason is that if a simulator tries to solve0=f(x)
, then any value ofx <= 0
is a solution, which can cause instability in the solver. Note that this problem does not exist for constant functions, as their first derivate will replaced due to optimization within the solver. - Do not replace an equation with a constant that has 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 rateV_flow
is zero, one may be inclined to use a construct of the formdp = smooth(1, if V_flow == 0 then 0 else f(V_flow));
. The problem with this formulation is that forV_flow=0
, the derivative isdp/dV_flow = 0
. However, the limitdp/dV_flow
, as|V_flow|
tends to zero, may be non-zero. Hence, the first derivative has a discontinuity atV_flow=0
, which can cause a solver to fail to solve the equation because thesmooth
statement declared that the first derivative exists and is continuous. - 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.
The NHES system in the Hybrid repository has the templating structure seen below.
The top level is the overall system package which incorporates all of the Modelica models held within the NHES package. Then inside of the package are the different subpackages (Systems, Electrical, Thermal, etc…). Within each of the subpackages are further subpackages as seen in the Systems package. Within the Systems package there are further subpackages called SubSystem Category (Examples, PrimaryHeatSystem, EnergyStorage, etc…). Then within these SubSystem Categories there is yet another level of subpackage that is called SubSystem_Specific. Within the SubSystem_Specific category is where development takes place and potential configurations of the different processes take shape. Inside each SubSystem_Specific there is a template that includes Examples, Subsystem Dummy, CS_Dummy, ED_Dummy, Data, BaseClasses, and usually a Components folder. For existing systems the Examples folder contains a runnable example the user can execute to see how the code runs at a top level and what scenarios it is capable of running.
-
Packages are first sorted alphabetically:
Actuators Boilers Chillers HeatExchangers
-
After alphabetical sorting, the following packages, if they exist, are moved to the front:
UsersGuide Examples
and the following packages, if they exist, are moved to the end:
Sources Sensors Media Interfaces Types Data Utilities (functions, records, etc.) Icons BaseClasses
- Use the
smoothOrder
annotation if a function is differentiable.
- Implement at least one regression test for each model and block, and run the regression tests. Regression tests should cover all branches of
if-then
constructs. Construction of Regression Tests within the HYBRID system is available in the "Developing Regression Tests" wiki page.