6. Organizing models
Code structuring and refactoring concepts illustrated on the “vehicule suspension” example. Indeed, in the previous sessions, we have created two models for the suspension. First an equation based model (ODE), then a model based on the acausal connection of physical components from the Modelica Standard Library.
Inheritance: extending models with subclassing
Packages: structuring a set of models
6.1. Inheritance: extending models with subclassing
Objective: avoid repetition, as expressed in the DRY (Don’t Repeat Yourself) principle.
Modelica keyword: extend
Ressources: Michael Tiller’s online book “Modelica by Example” [Tiller-2014], “Basic Equations” chapter:
For this exercise on inheritance, you can use your own code from the previous sessions, but if there is a problem, here are two fresh models. You can observe that many declarations are duplicated, especially the parameters.
model suspensionODE "1D model of a vehicle suspension. Illustration of a simple ODE."
Real z "position";
Real v "velocity";
parameter Real z0 = 1 "initial position";
parameter Real m = 1e3 "mass";
parameter Real k = 30e3 "spring constant";
parameter Real a = 2e3 "damping factor, to be increased to reduce oscillations";
initial equation
z = z0;
v = 0;
equation
der(z) = v;
m*der(v) = -a*v -k*z;
annotation(experiment(StartTime=0,StopTime=3));
end suspensionODE;
model suspensionComponents "1D model of a vehicle suspension. Illustration of a simple connection of components"
parameter Real z0 = 1 "initial position";
parameter Real m = 1e3;
parameter Real k = 30e3 "spring constant";
parameter Real a = 2e3 "damping factor, to be increased to reduce oscillations";
Modelica.Mechanics.Translational.Components.Fixed fixed1 annotation(Placement(visible = true, transformation(origin = {0, -60}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Mechanics.Translational.Components.Mass mass1(m = m, s(fixed = true, start = z0), v(fixed = true)) annotation(Placement(visible = true, transformation(origin = {0, 50}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
Modelica.Mechanics.Translational.Components.Spring spring1(c = k) annotation(Placement(visible = true, transformation(origin = {-20, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
Modelica.Mechanics.Translational.Components.Damper damper1(d = a) annotation(Placement(visible = true, transformation(origin = {20, -10}, extent = {{-10, -10}, {10, 10}}, rotation = 90)));
equation
connect(damper1.flange_a, fixed1.flange) annotation(Line(points = {{20, -20}, {20, -40}, {0, -40}, {0, -60}}, color = {0, 127, 0}));
connect(spring1.flange_a, fixed1.flange) annotation(Line(points = {{-20, -20}, {-20, -40}, {0, -40}, {0, -60}}, color = {0, 127, 0}));
connect(damper1.flange_b, mass1.flange_a) annotation(Line(points = {{20, 0}, {20, 0}, {20, 20}, {0, 20}, {0, 40}, {0, 40}}, color = {0, 127, 0}));
connect(spring1.flange_b, mass1.flange_a) annotation(Line(points = {{-20, 0}, {-20, 0}, {-20, 20}, {0, 20}, {0, 40}, {0, 40}}, color = {0, 127, 0}));
annotation(experiment(StartTime = 0, StopTime = 3), uses(Modelica(version = "4.0.0")));
end suspensionComponents;
Exercise
Refactor these two suspension models so that they inherit from one PartialSuspension
Bonus Exercise
Open the Resistor
, Capacitor
and Inductor
model of the
Modelica.Electrical.Analog.Basic
library.
Create a class diagram showing these models along with their parent classes.
A small usability problem: if you close OMEdit and reopen one of refactored models which inherits from the abstract model, you’ll get errors because it cannot be found:
[2] 17:42:43 Translation Error
[suspensionComponents: 2:3-2:29]: Base class suspensionAbstract not found in scope suspensionComponents.
(also the icon is a red crossed square).
We need to tell OpenModelica that these models “live in the same building”. → this is exactly the purpose of package…
6.2. Packages: structuring a set of models
A Modelica package (like in Python) is a way to store together a coherent set of models (a library). As an example taken from a workshop rather than the programming world, models for a Hammer and a Screwdriver could be stored in a package named Toolbox.
6.2.1. Package creation on OMEdit
Step 1, package creation Fig. 6.1:
Create a new model named Toolbox
,
but select the model “Specialization” to Package
(rather than the default choice Model
).
Important: uncheck the default choice “Save contents in one file”.
Now save the package and observe the result with a file browser.
Step 2, model creation within the package (Fig. 6.2):
In the Libraries Brower, right-click the package to create a new model Hammer
from the context menu of the package.
Observe that the “Insert in class” option is set to Toolbox
.
Again, observe the result in a file brower. Also notice the first line of the Hammer
model.
Question
Summarize the file structure of a Modelica package in a diagram showing the layout of the files and the key syntax elements in those files.
In particular, how many times is the package name Toolbox
used?
6.2.2. Refactoring existing code in a package
Now that you have seen how a package is created from scratch, let’s use this knowlegde on existing models. This probably requires making some edits outside OMEdit, typically in a text editor like Notepad++. This is because during the modification process, some files are temporarily invalid Modelica.
Exercise
Refactor the three suspension models so that they are in one package
SuspensionPackage
.
6.2.3. Bonus for Packages
Look at the Modelica.Electrical.Analog
package to see how it extends
from Modelica.Icons.Package
. Use the same trick to get a nice icon for your package.
Then you can customize it in the Icon View.