6. Runtime Components

6.1. Console Printer Component

The console printer component is used for printing directly to the system console utilizing the Java format string syntax and conversions. The component has the following methods:

print

Parameters:String message, ? values
Returns:Void
Description:This method prints the message formatted with the values to the console WITHOUT a new line.

println

Parameters:String message, ? values
Returns:Void
Description:This method prints the message formatted with the values to the console WITH a new line.

Following is a MaBL spec ( MaBL spec ) that demonstrates how to initialize the component and use it.

To utilize the component the following steps are necessary:

  • Import the component at the top of the MaBL spec (line 3).
  • Load the ConsolePrinter component by calling load(...) with the component name (line 6).
MaBL spec showcasing the console printer component.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
simulation 
import FMI2;
import ConsolePrinter;
@Framework("FMI2");
{
    ConsolePrinter consoleprinter = load("ConsolePrinter");

    string string_val = "a string";
    consoleprinter.println("String value: %s", string_val);

    int int_val = 1;
    consoleprinter.print("Integer value: %d", int_val);

    bool boolean_val = true;
    consoleprinter.print("Boolean value: %b", boolean_val);

    real double_val = 1.0;
    consoleprinter.println("Double value: %.1f", double_val);

    consoleprinter.println("All raw values: %d, %.1f, %b, %s", 1, 1.0, true, "a string");
    
    consoleprinter.println("All variables: %d, %.1f, %b, %s", int_val, double_val, boolean_val, string_val);

    if( consoleprinter != null )
    {
        unload(consoleprinter);
    }
}

6.2. Variable Step Component

The variable step component is used for calculating a variable step size during simulation. The component has the following methods:

setFMUs

Parameters:string names[], FMI2 fmus[]
Returns:VariableStepConfig
Description:This method specifies the FMUs that are of relevance for the ports that are to be used for calculating the step size. An array of fully qualifying FMU names, i.e. {<name of FMU>}.<name of instance>, should be passed together with an array of the FMUs. The method returns a VariableStepConfig object.

Attention

It is expected that the indices of the arrays are matching. I.e. the name found on the first index in the array of names is the name of the first FMU in the array of FMUs.

initializePortNames

Parameters:VariableStepConfig configuration, string portNames[]
Returns:Void
Description:This method specifies the names of the ports from which values are used to calculate a step. A VariableStepConfig and an array of port names are expected to be passed.

Attention

It is expected that the port names matches port values that are passed in the function addDataPoint. I.e. the first index in the array of port names are the port name of the value that are found on the first index in the array of port values.

addDataPoint

Parameters:VariableStepConfig configuration, real time, ? values
Returns:Void
Description:This method adds a data point, i.e. port values, to a given time. A VariableStepConfig, a real value representing the time and a collection of port values are expected to be passed.

Attention

It is expected that the port values matches the port names that are passed in the function initializePortNames. I.e. the first index in the array of port values are the value of the port name that are found on the first index in the array of port names.

getStepSize

Parameters:VariableStepConfig configuration
Returns:Real
Description:This method returns a step size as a real. It is expected that port names have been initialized and that a data point has been added for the given time. A VariableStepConfig is expected to be passed.

setEndTime

Parameters:VariableStepConfig configuration, real endTime
Returns:Void
Description:This method sets the end time of the simulation. A VariableStepConfig and a real representing the end time of the simulation are expected to be passed.

isStepValid

Parameters:VariableStepConfig configuration, real nextTime, ? values
Returns:bool
Description:This method validates if a given step is valid. A VariableStepConfig, a real representing the time and an a collection of port values are expected to be passed. The method returns a boolean indicating if the step is valid or not.

Following is a snippet of a MaBL spec that demonstrates how to initialize the component and use it.

To initialize the component the following steps are necessary:

  • Import the component at the top of the MaBL spec.
  • Load the VariableStep component by calling load(...) with the component name and a path to the config.json file (line 98).
  • Retrieve a VariableStepConfig object by calling setFMUs(...) with FMUs and their corresponding names (line 99).
  • Specify the port names of values that are to be passed subsequently by calling initializePortNames(...) (line 101).
  • Specify the end time of the simulation by calling setEndTime(...) (102).

To calculate a step-size after initialization of the component the following steps are necessary:

  • Add a datapoint for the current simulation time by calling addDataPoint(...) (line 135).
  • Get the step-size by calling getStepSize(...) (line 136).

It is also possible to validate a step-size by calling isStepValid(...) with the new port values and simulation time after stepping each FMU (line 157).

Lastly the component should be unloaded by calling unload(varaibleStep) (line 183).

Snippet of a MaBL spec showcasing the variable step component.
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    // #############################
    // Setup of variable step
    // #############################
    FMI2 FMUs[2] = {tankController, singleWatertank};
    string FMUInstanceNames[2] = {"{control}.c", "{tank}.t"};
    VariableStep variableStep = load("VariableStep", "src/test/resources/variable_step/config.json");
    VariableStepConfig variableStepConfig = variableStep.setFMUs(FMUInstanceNames, FMUs);
    string portNames[3] = {"{tank}.t.level","{control}.c.maxlevel", "{control}.c.minlevel"};
    variableStep.initializePortNames(variableStepConfig, portNames);
    variableStep.setEndTime(variableStepConfig, END_TIME);
    real portValues[3] = {wtLevelOutputValue[0], 2.0, 1.0};


    // #############################
    // Simulation Loop until END_TIME
    // #############################
    real time = START_TIME;
    while(time + STEP_SIZE <= END_TIME)
    {
        // #############################
        // Convert valve state from boolean to real
        // #############################
        if( crtlValveStateOutput[0] )
        {
            wtValveStateInput = 1.0;
        }
        else
        {
            wtValveStateInput = 0.0;
        }
        // #############################
        // Set the valve state on the tank
        // Set the level on the controller
        // #############################
        wtValveStateInputs[0] = wtValveStateInput;
        wtInstance.setReal(wtValveStateValRef, 1, wtValveStateInputs);
        crtlInstance.setReal(crtlLevelInputValRef, 1, wtLevelOutputValue);


        // #############################
        // Get step size from variable step
        // #############################
        variableStep.addDataPoint(variableStepConfig, time, portValues);
        STEP_SIZE = variableStep.getStepSize(variableStepConfig);

        // #############################
        // Step the tank
        // Step the controller
        // #############################
        wtInstance.doStep(time, STEP_SIZE, true);
        crtlInstance.doStep(time, STEP_SIZE, true);

        // #############################
        // Get the valve state from the controller
        // Get the level from the tank
        // #############################
        crtlInstance.getBoolean(crtlValveStateValRef, 1, crtlValveStateOutput);
        wtInstance.getReal(wtLevelValRef, 1, wtLevelOutputValue);


        // #############################
        // Validate step size
        // #############################
        portValues[0] = wtLevelOutputValue[0];
        bool validStepSize = variableStep.isStepValid(variableStepConfig, time + STEP_SIZE, portValues);
        //if(!validStepSize)
        //    break;

        // #############################
        // Increase the time with STEP_SIZE
        // Write the valve state and the water level to the results
        // #############################
        time = time + STEP_SIZE;
        dataWriter.writeDataPoint(dataWriterConfiguration, time, crtlValveStateOutput[0], wtLevelOutputValue[0]);

    }

    // #############################
    // Clean up
    // #############################
    dataWriter.close();
    wtInstance.terminate();
    crtlInstance.terminate();
    tankController.freeInstance(crtlInstance);
    singleWatertank.freeInstance(wtInstance);

    unload(tankController);
    unload(singleWatertank);
    unload(dataWriter);

    unload(variableStep);

6.3. Runtime Plugins

Note

This section has yet to be filled out