Modelling Physical Systems¶
We will do the following:
Model a water tank in Modelica;
Compile the Modelica model into an FMU;
Write a simple SMOL program that loads the FMU;
Simulate and control the system’s behavior over time
Behavior of a Watertank¶
We will model a watertank with a pipe, such that turning on the pipe adds a constant amount of water per second to the current level of the tank. The tank also has a drain hole at the bottom; the rate of outflow is dependent on the current water level of the tank.
Mathematically, the behavior of the tank can be described by the following formula:
where
\(l\): current level in tank
\(d\): drain rate, “size of the hole”
\(f\): rate of inflow
\(v\): valve control (0: valve is closed, 1: valve is open)
The Watertank in Modelica¶
The following Modelica model implements the watertank. Note that we use a Boolean variable to model the valve status, and introduce a second equation explicitly defining the current inflow from the valve.
model Tank
parameter Real d = 0.5 "drain rate / 'size of hole'";
parameter Real f = 1.0 "fill rate in l/s (constant)";
input Boolean v(start = true) "Valve closed / open";
output Real l(start = 5) "water level";
Real inFlow "Current fill rate";
equation
der(l) = inFlow - d * l;
if v then inFlow = f; else inFlow = 0.0; end if;
end Tank;
Creating an FMU for the Watertank¶
OpenModelica can export Modelica models as FMUs. This can be done by opening
the model in the OMEdit application, or from the command line via the omc
program. To generate an FMU from the command line, save the above model in a
file simple_tank.mo
and create a file generate_fmu.mos
with the
following content:
installPackage(Modelica);
loadModel(Modelica);
loadFile("simple_tank.mo");
buildModelFMU(Tank, version="2.0", fmuType="me_cs");
getErrorString()
Then, run the command omc generate_fmu.mos
, which should result in a file
Tank.fmu
.
Controlling the Watertank from SMOL¶
SMOL can instantiate an FMU and control it. Create a file simple_tank.smol
with the following contents:
main
FMO[in Boolean v, out Double l] de =
simulate("Tank.fmu", v = False, d = 0.5, f = 1.0);
print(de.l);
while de.l > 2 do
de.tick(1.0);
print(de.l);
end
de.v = True;
while de.l < 5 do
de.tick(1.0);
print(de.l);
end
end
This SMOL program creates an instance of the tank FMU and instantiates its parameters and inputs (Lines 2-3), advances time until the water level in the tank decreases below 2 (Lines 5-8), then turns on the valve (Line 9) and advances time until the water level increases above 5 (Lines 10-13).