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.

  1. Inheritance: extending models with subclassing

  2. 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”.

_images/OMEdit_Package_new.png

Fig. 6.1 Creation of a Package named Toolbox, to be saved in multiple files

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.

_images/OMEdit_Package_Model_within.png

Fig. 6.2 Creation of a Model named Hammer within the existing Toolbox package

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.