In this section, we’ll show how to create basic components for modeling one-dimensional rotational systems. We’ll build on our discussion of rotational connectors and show how they can be used to define the interfaces for basic rotational components. Finally, we’ll show how those rotational components can then be assembled into a system model that replicates the behavior of the equation-based version of the same system presented in the first chapter.
In the first chapter, we considered A Mechanical Example modeled strictly in terms of equations (i.e., without component models). In this section, we will start by recreating that system model using components. To do this, we first have to define models for the fundamental components we require. These will consist of models for an inertia, a spring, a damper and a mechanical ground.
As in the previous section, we will first define the component models using verbose formulations and then we will revisit these definitions and attempt to factor out common code to avoid repetition across component models.
The method for creating these models will be very similar to how we previously created component models in the heat transfer and electrical domains. But before we start building component models, we should first discuss one of the complexities associated with mechanical systems, coordinate systems.
In the mechanical domain, the conserved quantity we will be tracking is momentum. What makes momentum different from the conserved quantities we’ve already covered, heat and charge, is that it is directional. Since we are only concerning ourselves with the one dimensional case here, the consequence of this directionality is that momentum is a signed quantity (i.e., it can be positive or negative).
Consider a rotating mass with a moment of inertia, . If the angular position of the inertia is represented by , then the angular velocity of the inertia, , is defined as:
Obviously, a positive value of will result in an increase in over time. Furthermore, the angular acceleration of the inertia, , is defined as:
As with the angular velocity, we can see that a positive value for will result in an increase in the angular velocity. Finally, the angular momentum of this rotating inertia is defined as and we know from Euler’s laws of motion that (assuming J is a constant):
From this relationship, it is clear that a positive value for the torque, , will increase the amount of momentum stored in the mass.
The point of presenting all these relationships is to underscore the sign conventions associated with , , and . They are all tied to the fundamental definition of what a positive angular position is. Whatever direction causes to increase is the same direction that corresponds to a positive velocity, a positive acceleration and a positive torque.
With this discussion about sign conventions and coordinate systems out of the way, we can start creating our component models. We’ll start with the inertia model:
within ModelicaByExample.Components.Rotational.VerboseApproach; model Inertia "Rotational inertia without inheritance" parameter Modelica.SIunits.Inertia J; Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a annotation Modelica.Mechanics.Rotational.Interfaces.Flange_b flange_b annotation protected Modelica.SIunits.Angle phi_rel; Modelica.SIunits.Torque tau; Modelica.SIunits.AngularVelocity w; equation // Variables phi_rel = flange_a.phi-flange_b.phi; tau = flange_a.tau; w = der(flange_a.phi); // Conserviation of angular momentum (includes storage) J*der(w) = flange_a.tau + flange_b.tau; // Kinematic constraint (inertia is rigid) phi_rel = 0; annotation
Inertia model includes two “flanges”, one on either end. The
significance of these flanges is made clearer from the icon of the
In other words, the
Inertia model includes a flange on either end.
You can think of this model as a shaft with connectors on either end.
Now, the fundamental equation we wish to capture in the
J*der(w) = flange_a.tau + flange_b.tau;
This is basically expressing the fact that the increase in momentum
stored within the inertia is equal to the sum of the torques applied
to the inertia. Recall, from our previous discussions on
Acausal Connections, that the sign convention for flow
variables on connectors (
flange_b.tau in this
case) is that a positive value represents a flow of the conserved
quantity into the component model. The fact that
flange_b have the same sign convention means that the
model is symmetric (i.e., it can be flipped over and it doesn’t
change the behavior).
However, this equation refers to the internal variables
represents ) and
tau so we need to include
declarations and definitions for those variables as well.
Next, let us consider the definition of a spring model:
within ModelicaByExample.Components.Rotational.VerboseApproach; model Spring "Rotational spring without inheritance" parameter Modelica.SIunits.RotationalSpringConstant c; Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a annotation Modelica.Mechanics.Rotational.Interfaces.Flange_b flange_b annotation protected Modelica.SIunits.Angle phi_rel; Modelica.SIunits.Torque tau; equation // Variables phi_rel = flange_a.phi-flange_b.phi; tau = flange_a.tau; // No storage of angular momentum flange_a.tau + flange_b.tau = 0; // Hooke's law tau = c*phi_rel; end Spring;
The icon for our spring model is rendered as:
Inertia model, the
Spring model has two connectors,
one on each end. It also defines many of the same internal
variables. Ultimately, the behavior of the spring comes down to this
tau = c*phi_rel;
In fact, apart from this equation and the parameter
c, much of the
content in the
Spring model is the same as the content in the
Damper model is also very similar to the
Again, the main differences are the parameter (
d in this case) and
within ModelicaByExample.Components.Rotational.VerboseApproach; model Damper "Rotational damper without inheritance" parameter Modelica.SIunits.RotationalDampingConstant d; Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a annotation Modelica.Mechanics.Rotational.Interfaces.Flange_b flange_b annotation protected Modelica.SIunits.Angle phi_rel; Modelica.SIunits.Torque tau; equation // Variables phi_rel = flange_a.phi-flange_b.phi; tau = flange_a.tau; // No storage of angular momentum flange_a.tau + flange_b.tau = 0; // Damping relationship tau = d*der(phi_rel); end Damper;
The icon for the
Damper model is rendered as:
We already have models for an inertia, a spring and a damper. The only model we are missing in order to complete our dual spring mass damper system is a model of mechanical ground. But before we complete that model, let’s take a moment to revisit the models we’ve already created with the goal of factoring out the large amount of code shared between these models. As in the previous section, let’s take the time to apply the DRY (Don’t Repeat Yourself) principle.
It is worth noting that because the Modelica Standard Library has an
extensive collection of rotational components, it was forced to deal
with this issue of redundant code almost from the start. However, we
will not be using the
partial models from the Modelica Standard
Library here simply because they are designed to deal with many other
cases that are not relevant in this context. As a result, it’s
complexity (although necessary) makes it unsuitable pedagogically.
But one thing we will preserve from the Modelica Standard Library is
the need for multiple
partial models. This need arises from the
fact that, unlike in our previous discussion of
Electrical Components, our rotational component models share
different amounts of code with each other.
What is common to all of our models is the existence of two flange
flange_b. However, while the
Inertia model has the capacity to store angular momentum, the
Damper models do not. As a result, the
conservation equations are different among these components.
Let’s start with the elements that are common to all three models.
These are represented by the following
within ModelicaByExample.Components.Rotational.Interfaces; partial model TwoFlange "Definition of a partial rotational component with two flanges" Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a annotation Modelica.Mechanics.Rotational.Interfaces.Flange_b flange_b annotation protected Modelica.SIunits.Angle phi_rel; equation phi_rel = flange_a.phi-flange_b.phi; end TwoFlange;
In addition to defining the two flanges,
flange_b, this model also defines the relative angle between these
phi_rel. Of course, this model is also marked as
partial since it is missing any description of the component’s
We could have all three models inherit from this model. But then we
would still have some redundant equations between our
Damper model. So we will instead create a slightly more
specialized version of the
TwoFlange model to represent compliant
models that do not store momentum:
within ModelicaByExample.Components.Rotational.Interfaces; partial model Compliant "A compliant rotational component" extends ModelicaByExample.Components.Rotational.Interfaces.TwoFlange; protected Modelica.SIunits.Torque tau; equation tau = flange_a.tau; flange_a.tau + flange_b.tau = 0 "Conservation of angular momentum (no storage)"; end Compliant;
Compliant model adds on additional internal variable (to
represent the torque that passes through the component from
flange_b) and an equation indicating that no
angular momentum is stored by the component.
With these base classes defined, let us quickly revisit the various component model definitions to see how much more succinct they can be made by using inheritance.
TwoFlanges model, our
Inertia model can be
within ModelicaByExample.Components.Rotational.Components; model Inertia "A rotational inertia model" parameter Modelica.SIunits.Inertia J; extends ModelicaByExample.Components.Rotational.Interfaces.TwoFlange; Modelica.SIunits.AngularVelocity w "Angular Velocity" annotation Modelica.SIunits.Angle phi "Angle" annotation equation phi = flange_a.phi; w = der(flange_a.phi) "velocity of inertia"; phi_rel = 0 "inertia is rigid"; J*der(w) = flange_a.tau + flange_b.tau "Conservation of angular momentum with storage"; end Inertia;
In the same way, inheriting from the
Compliant model our
Spring model can be much more compactly represented as:
within ModelicaByExample.Components.Rotational.Components; model Spring "A rotational spring component" parameter Modelica.SIunits.RotationalSpringConstant c; extends ModelicaByExample.Components.Rotational.Interfaces.Compliant; equation tau = c*phi_rel "Hooke's Law"; end Spring;
Damper model is similarly simplified:
within ModelicaByExample.Components.Rotational.Components; model Damper "A rotational damper" parameter Modelica.SIunits.RotationalDampingConstant d; extends ModelicaByExample.Components.Rotational.Interfaces.Compliant; equation tau = d*der(phi_rel) "Damping relationship"; end Damper;
Finally, we can complete the one model remaining in order to complete our dual spring mass damper system. The mechanical ground model is defined as follows:
within ModelicaByExample.Components.Rotational.Components; model Ground "Mechanical ground" Modelica.Mechanics.Rotational.Interfaces.Flange_a flange_a annotation equation flange_a.phi = 0; end Ground;
Finally, we have all the parts we need in order to reconstruct the example we saw in the first chapter. Using the various components already defined in this section, the Modelica code for our component based system model looks like this:
within ModelicaByExample.Components.Rotational.Examples; model SMD Components.Ground ground annotation Components.Damper damper2(d=1) annotation Components.Spring spring2(c=5) annotation Components.Inertia inertia2( J=1, phi(fixed=true, start=1), w(fixed=true, start=0)) annotation Components.Damper damper1(d=0.2) annotation Components.Spring spring1(c=11) annotation Components.Inertia inertia1( J=0.4, phi(fixed=true, start=0), w(fixed=true, start=0)) annotation equation connect(ground.flange_a, damper2.flange_b) annotation connect(ground.flange_a, spring2.flange_b) annotation connect(damper2.flange_a, inertia2.flange_b) annotation connect(spring2.flange_a, inertia2.flange_b) annotation connect(inertia2.flange_a, damper1.flange_b) annotation connect(inertia2.flange_a, spring1.flange_b) annotation connect(damper1.flange_a, inertia1.flange_b) annotation connect(spring1.flange_a, inertia1.flange_b) annotation end SMD;
The diagram for this model, when rendered, looks like this:
This completes our discussion of basic rotational components. But there is quite a bit more to say about rotational components in the next section on Advanced Rotational Components.