11. Code Generation¶
11.1. Introduction¶
This section describes the translation of control sequences expressed in CDL to a building automation system (BAS). The translation needs to be done only if the target BAS does not support CDL.
Translating the CDL library to a BAS to make it available as part of a product line needs to be done only when the CDL library is updated, and hence only developers need to perform this step. However, translation of a CDL-conforming control sequence that has been developed for a specific building will need to be done for each building project.
While translation from CDL to C code or to a Functional Mockup Unit is support by Modelica simulation environments, translation to legacy building automation product lines is more difficult as they typically do not allow executing custom C code. Moreover, a building operator typically needs a graphical operator interface, which would not be supported if one were to simply upload compiled C code to a BAS.
Use of CDL control sequences for building operation, or use of such sequences in a verification test module, consists of the following steps:
Implementation of the control sequence using CDL.
Export of the CDL sequence as a Functional Mockup Unit for Model Exchange (FMU-ME) or as a CXF representation, which is serialized in JSON-LD.
Import of the FMU-ME in the runtime environment, or translation of the CXF representation of the control sequence to the language used by the target BAS.
Fig. 11.1 shows the process of creating a CDL control sequence and translating it into different target platforms.
Fig. 11.1 Overview of CDL control sequence creation, verification and translation into differne target platforms.¶
The next section describes three different approaches that can be used by control vendors to translate CDL to their product line:
Translation of the CDL-compliant sequence to intermediate CXF representation, which can be translated to the format used by the control platform (Section 11.3).
Export of the whole CDL-compliant sequence using the FMI standard (Section 11.4), a standard for exchanging simulation models that can be simulated using a variety of open-source tools.
Translation of the CDL-compliant sequence to an xml-based standard called System Structure and Parameterization (SSP), which is then used to parameterize, link and execute pre-compiled elementary CDL blocks (Section 11.5).
The best approach will depend on the control platform. While in the short-term, option 1) is likely preferred as it allows reusing existing control product lines, the long term vision is that control product lines would directly compile CDL using option 2) or 3). Before explaining these three approaches, we first discuss challenges of translation of CDL sequences to a BAS, as well as their implications.
11.2. Challenges and Implications for Translation of Control Sequences from and to Building Control Product Lines¶
This section discusses challenges and implications for translating CDL-conforming control sequences to the programming languages used by the target BAS.
First, we note that simply generating C code is not viable for such applications because a BAS generally does not allow users to upload C code. Moreover, they also need to provide an interface for the building operator that allows editing the control parameters and control sequences.
Second, we note that the translation will for most systems, if not all,
only be possible from CDL to a BAS,
but not vice versa. This is due to specific constructs that may exist
in the BAS but not in CDL. For example,
if Sedona (https://www.sedona-alliance.org/)
were the target platform, then
translating from Sedona to CDL will not be possible
because Sedona allows boolean variables
to take on the values true, false and null, but
CDL has no null value.
11.3. Translation of a Control Sequence using a Intermediate CXF (JSON-LD) Format¶
Control companies that choose to not use the C-code generation approach or
the FMI standard to execute CDL-compliant control sequences can develop translators
from CDL to their BAS’s programming language. To aid in this process, an intermediate
Control eXchange Format (CXF) can be used. As mentioned in Section 8
CXF is a JSON-LD representation of a CDL sequence, serialized in JSON.
Modelica-json
is an implementation of such a CDL to CXF translator.
This translator first parses CDL-compliant control sequences to an abstract
syntax tree in JSON format and then generates a CXF representation from it.
Modelica-json can also parse Modelica code and it
can generate the following output formats:
a JSON representation of the abstract syntax tree of the control sequence (CDL) or the Modelica file (
raw-json),a simplified version of this JSON representation (
json),a semantic model from the control sequence or the Modelica file (
semantic),a CXF representation of the control sequence (
cxf) andan html-formated documentation of the control sequence (
docanddoc+).
Please refer to the modelica-json documentation for more information.
To translate CDL-compliant control sequences to the programming language that is
used by the target BAS, cxf output format is most
suited. Developers can choose to treat the CXF representation as a
simple JSON file or as a linked-data Resource Description Framework (RDF) graph.
The latter option is recommended if the target BAS
supports RDF or other semantic web technologies.
As an illustrative example, consider the composite control block shown in Fig. 7.3 and reproduced in Fig. 11.2.
Fig. 11.2 Example of a composite control block that outputs \(y = \max( k \, e, \, y_{max})\) where \(k\) is a parameter.¶
In CDL, this would be specified as
1block CustomPWithLimiter
2 "Custom implementation of a P controller with variable output limiter"
3 parameter Real k "Constant gain";
4 CDL.Interfaces.RealInput yMax "Maximum value of output signal"
5 annotation (Placement(transformation(extent={{-140,20},{-100,60}})));
6 CDL.Interfaces.RealInput e "Control error"
7 annotation (Placement(transformation(extent={{-140,-60},{-100,-20}})));
8 CDL.Interfaces.RealOutput y "Control signal"
9 annotation (Placement(transformation(extent={{100,-10},{120,10}})));
10 CDL.Reals.MultiplyByParameter gain(final k=k) "Constant gain"
11 annotation (Placement(transformation(extent={{-60,-50},{-40,-30}})));
12 CDL.Reals.Min minValue "Outputs the minimum of its inputs"
13 annotation (Placement(transformation(extent={{20,-10},{40,10}})));
14equation
15 connect(yMax, minValue.u1) annotation (
16 Line(points={{-120,40},{-120,40},{-20,40},{-20, 6},{18,6}}, color={0,0,127}));
17 connect(e, gain.u) annotation (
18 Line(points={{-120,-40},{-92,-40},{-62,-40}}, color={0,0,127}));
19 connect(gain.y, minValue.u2) annotation (
20 Line(points={{-39,-40},{-20,-40},{-20,-6}, {18,-6}}, color={0,0,127}));
21 connect(minValue.y, y) annotation (
22 Line(points={{41,0},{110,0}}, color={0,0,127}));
23 annotation (Documentation(info="<html>
24<p>
25Block that outputs <code>y = min(yMax, k*e)</code>,
26where
27<code>yMax</code> and <code>e</code> are real-valued input signals and
28<code>k</code> is a parameter.
29</p>
30</html>"));
31end CustomPWithLimiter;
This specification can be converted to CXF using the program modelica-json. Executing the command
node modelica-json/app.js -f CustomPWithLimiter.mo -o cxf -p
will produce a file called CustomPWithLimiter.jsonld that
looks as follows:
1{
2 "@context": {
3 "S231": "http://data.ashrae.org/S231#"
4 },
5 "@graph": [
6 {
7 "@id": "http://example.org#FromModelica.CustomPWithLimiter",
8 "@type": "S231:Block",
9 "S231:containsBlock": [
10 {
11 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain"
12 },
13 {
14 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue"
15 }
16 ],
17 "S231:documentation": "info=<html>\n<p>\nBlock that outputs <code>y = min(yMax, k*e)</code>,\nwhere\n<code>yMax</code> and <code>e</code> are real-valued input signals and\n<code>k</code> is a parameter.\n</p>\n</html>",
18 "S231:hasInput": [
19 {
20 "@id": "http://example.org#FromModelica.CustomPWithLimiter.e"
21 },
22 {
23 "@id": "http://example.org#FromModelica.CustomPWithLimiter.yMax"
24 }
25 ],
26 "S231:hasOutput": {
27 "@id": "http://example.org#FromModelica.CustomPWithLimiter.y"
28 },
29 "S231:hasParameter": {
30 "@id": "http://example.org#FromModelica.CustomPWithLimiter.k"
31 },
32 "S231:label": "CustomPWithLimiter"
33 },
34 {
35 "@id": "http://example.org#FromModelica.CustomPWithLimiter.e",
36 "@type": "S231:RealInput",
37 "S231:accessSpecifier": "public",
38 "S231:description": "Control error",
39 "S231:graphics": "Placement(transformation(extent={{-140,-60},{-100,-20}})))",
40 "S231:isConnectedTo": {
41 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.u"
42 },
43 "S231:label": "e"
44 },
45 {
46 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain",
47 "@type": "http://example.org#Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter",
48 "S231:accessSpecifier": "public",
49 "S231:description": "Constant gain",
50 "S231:graphics": "Placement(transformation(extent={{-60,-50},{-40,-30}})))",
51 "S231:hasInstance": [
52 {
53 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.k"
54 },
55 {
56 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.u"
57 },
58 {
59 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.y"
60 }
61 ],
62 "S231:label": "gain"
63 },
64 {
65 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.k",
66 "S231:isFinal": true,
67 "S231:value": "k"
68 },
69 {
70 "@id": "http://example.org#FromModelica.CustomPWithLimiter.gain.y",
71 "S231:isConnectedTo": {
72 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.u2"
73 }
74 },
75 {
76 "@id": "http://example.org#FromModelica.CustomPWithLimiter.k",
77 "@type": "S231:Parameter",
78 "S231:accessSpecifier": "public",
79 "S231:description": "Constant gain",
80 "S231:isOfDataType": {
81 "@id": "S231:Real"
82 },
83 "S231:label": "k",
84 "S231:value": 2
85 },
86 {
87 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue",
88 "@type": "http://example.org#Buildings.Controls.OBC.CDL.Reals.Min",
89 "S231:accessSpecifier": "public",
90 "S231:description": "Outputs the minimum of its inputs",
91 "S231:graphics": "Placement(transformation(extent={{20,-10},{40,10}})))",
92 "S231:hasInstance": [
93 {
94 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.u1"
95 },
96 {
97 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.u2"
98 },
99 {
100 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.y"
101 }
102 ],
103 "S231:label": "minValue"
104 },
105 {
106 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.y",
107 "S231:isConnectedTo": {
108 "@id": "http://example.org#FromModelica.CustomPWithLimiter.y"
109 }
110 },
111 {
112 "@id": "http://example.org#FromModelica.CustomPWithLimiter.y",
113 "@type": "S231:RealOutput",
114 "S231:accessSpecifier": "public",
115 "S231:description": "Control signal",
116 "S231:graphics": "Placement(transformation(extent={{100,-10},{120,10}})))",
117 "S231:label": "y"
118 },
119 {
120 "@id": "http://example.org#FromModelica.CustomPWithLimiter.yMax",
121 "@type": "S231:RealInput",
122 "S231:accessSpecifier": "public",
123 "S231:description": "Maximum value of output signal",
124 "S231:graphics": "Placement(transformation(extent={{-140,20},{-100,60}})))",
125 "S231:isConnectedTo": {
126 "@id": "http://example.org#FromModelica.CustomPWithLimiter.minValue.u1"
127 },
128 "S231:label": "yMax"
129 }
130 ]
131}
The CXF representation can then be parsed and converted to another block-diagram
language.
Note that CDL.Reals.MultiplyByParameter is an elementary CDL block
(see Section 7.6).
When modelica-json encounters an instance of a
composite CDL block (see Section 7.12), it would be parsed recursively
until only elementary CDL blocks are present in the CXF file.
Various examples of CDL converted to CXF can be found at
https://github.com/lbl-srg/modelica-json/tree/master/test/FromModelica.
As shown in Fig. 11.1, the CXF representation has been used to translate a CDL sequence into different target BAS such as Automted Logic Corporation WebCTRL (CXF translated into ALC Eikon), Tridium Niagara, IEC 61131-10 programming logic controller (CDL-PLC) and Normal framework (CXF translated into JavaScript using Modelica Translator).
The simplified JSON representation of a CDL sequence must be compliant with the corresponding JSON Schema. A JSON Schema describes the data format and file structure, lists the required or optional properties, and sets limitations on values such as patterns for strings or extrema for numbers.
The CDL Schema can be found at https://github.com/lbl-srg/modelica-json/blob/master/schema-cdl.json .
The program modelica-json automatically tests the JSON representation parsed from a CDL file against the schema right after it is generated.
The validation of an existing JSON representation of a CDL file against the schema can be done executing the command
node modelica-json/validation.js -f filename.json
Control providers can use the JSON Schema as a specification to develop a translator to a control product line. If JSON files are the starting point, then they should first validate the JSON files against the JSON Schema, as this ensures that the input files to the translator are valid.
11.4. Export of a Control Sequence or a Verification Test using the FMI Standard¶
This section describes how to export a control sequence, or a verification test, using the FMI standard. In this workflow, the intermediate format that is used is FMI for model exchange or FMI for co-simulation, as it is an open standard, and because FMI can easily be integrated into tools for controls or verification using a variety of languages.
Note
Also possible, but outside of the scope of this project, is the translation of the control sequences to JavaScript, which could then be executed in a BAS. For a Modelica to JavaScript converter, see https://github.com/tshort/openmodelica-javascript.
To implement control sequences, blocks from the CDL library (Section 7.6) can be used to compose sequences that conform to the CDL language specification described in Section 7. For verification tests, any Modelica block can be used. Next, to export the Modelica model, a Modelica tool such as OpenModelica, Impact, OPTIMICA or Dymola can be used. For example, with OPTIMICA a control sequence can be exported using the Python commands
from pymodelica import compile_fmu
compile_fmu("Buildings.Controls.OBC.ASHRAE.G36.AHUs.SingleZone.VAV.Economizers.Controller")
This will generate an FMU-ME. Finally, to import the FMU-ME in a runtime environment, various tools can be used, including:
Tools based on Python, which could be used to interface with Volttron (https://www.energy.gov/eere/buildings/volttron):
PyFMI (https://pypi.org/pypi/PyFMI)
Tools based on Java:
Tools based on C:
FMI Library (https://github.com/modelon-community/fmi-library)
Modelica tools, of which many if not all provide functionality for real-time simulation:
OpenModelica (https://openmodelica.org/)
Dymola (https://www.3ds.com/products-services/catia/products/dymola/)
MapleSim (https://www.maplesoft.com/products/maplesim/)
SimulationX (https://www.esi-group.com/products/system-simulation)
SystemModeler (https://www.wolfram.com/system-modeler/)
See also https://fmi-standard.org/tools/ for other tools.
Note that Modelica models could also be compiled directly to a BAS leveraging the FMI for embedded systems eFMI that was developed technologies for running dynamic models on electronic control units (ECU), micro controllers or other embedded systems. This may be attractive for FDD and some advanced control sequences.
11.5. Modular Export of a Control Sequence using the FMI Standard for Control Blocks and using the SSP Standard for the Run-time Environment¶
In 2019, a new standard called System Structure and Parameterization (SSP) was released (https://ssp-standard.org/). The standard provides an xml scheme for the specification of FMU parameter values, their input and output connections, and their graphical layout. The SSP standard allows for transporting complex networks of FMUs between different platforms for simulation, hardware-in-the-loop and model-in-the-loop [KohlerHM+16]. Various tools that can simulate systems specified using the SSP standard are available, see https://ssp-standard.org/tools/.
CDL-compliant control sequences could be exported to the SSP standard as shown in Fig. 11.3.
Fig. 11.3 Translation of CDL to SSP.¶
In such a workflow, a control vendor would translate the elementary CDL blocks
(Section 7.6)
to a repository of FMU blocks. These blocks will then be used during operation.
For each project, its CDL-compliant control sequence could be translated
to the CXF, as described in Section 11.3.
Using a template engine (similar as is used
by modelica-json to translate the CDL sequence to html),
the CXF representation could then be converted to the xml syntax
specified in the SSP standard.
Finally, a tool such as the FMI Composer could import the
SSP-compliant specification, and execute the control sequence using
the elementary CDL block FMUs from the FMU repository.
Note
In this workflow, all key representations are based on standards: The CDL-specification uses a subset of the Modelica standard, the elementary CDL blocks are converted to the FMI standard, and finally the runtime environment uses the SSP standard.
11.6. Replacement of Elementary CDL Blocks during Translation¶
When translating CDL to a control product line, a translator may want to conduct certain substitutions. Some of these substitutions can change the control response, which can cause the verification that checks whether the actual implementation conforms to the specification to fail.
This section therefore explains how certain substitutions can be performed in a way that allows formal verification to pass. More details about how verification will be conducted can be found in Section 12.
11.6.1. Substitutions that Give Identical Control Response¶
Consider the gain CDL.Reals.MultiplyByParameter used above. If a product line
uses different names for the inputs, outputs and parameters, then they can
be replaced.
Moreover, certain transformations that do not change the response of the block are permissible: For example, consider the PID controller in the CDL library. The implementation has a parameter for the time constant of the integrator block. If a control vendor requires the specification of an integrator gain rather than the integrator time constant, then such a parameter transformation can be done during the translation, as both implementations yield an identical response.
11.6.2. Substitutions that Change the Control Response¶
If a control vendor likes to use for example a different implementation of the anti-windup in a PID controller, then such a substitution will cause the verification to fail if the control responses differ between the CDL-compliant specification and the vendor’s implementation.
Therefore, if a customer requires the implemented control sequence to comply with the specification, then the workflow shall be such that the control provider provides an executable implementation of its controller, and the control provider shall ask the customer to replace in the control specification the PID controller from the CDL library with the PID controller provided by the control provider. Afterwards, verification can be conducted as usual.
Note
Such an executable implementation of a vendor’s PID controller can
be made available by publishing the controller
or by contributing the controller to the Modelica Buildings Library.
The implementation of the control logic can be done either
using other CDL blocks, which is the preferred approach,
using the C language, or by providing
a compiled library. See the Modelica Specification [Mod23]
for implementation details
if C code or compiled libraries are provided.
If a compiled library is provided, then binaries shall be provided for
Windows 32/64 bit, Linux 32/64 bit, and OS X 64 bit.
11.6.3. Adding Blocks that are not in the CDL Library¶
If a control vendor likes to use a block that is not in the CDL library, such as a block that uses machine learning to schedule optimal warm-up, then such an addition must be approved by the customer. If the customer requires the part of the control sequence that contains this block to be verified, then the block shall be made available as described in Section 11.6.2.