When building subsystem models, it is extremely common for a subsystem to contain parameters that it then propagates or cascades down to its components. For example, consider the following system model used in our discussion of Basic Rotational Components:
within ModelicaByExample.Components.Rotational.Examples;
model SMD
Components.Damper damper2(d=1);
Components.Ground ground;
Components.Spring spring2(c=5);
Components.Inertia inertia2(J=1,
phi(fixed=true, start=1),
w(fixed=true, start=0));
Components.Damper damper1(d=0.2);
Components.Spring spring1(c=11);
Components.Inertia inertia1(
J=0.4,
phi(fixed=true, start=0),
w(fixed=true, start=0));
equation
// ...
end SMD;
If we wanted to use this model in different contexts where the values
of the component parameters, like d
, might vary, we could make
d
a parameter at the subsystem level and then propagate it down
into the hierarchy using a modification. The result would look
something like this:
within ModelicaByExample.Components.Rotational.Examples;
model SMD
import Modelica.SIunits.*;
parameter RotationalDampingConstant d;
Components.Damper damper2(d=d);
// ...
There is one complication here. It is possible for a user to come
along and change the value of damper2.d
instead of modifying the
d
parameter in the SMD
model. To avoid having the d
parameter and the damper2.d
parameter from getting out of sync
(having different values), we can permanently bind them using the
final
qualifier:
within ModelicaByExample.Components.Rotational.Examples;
model SMD
import Modelica.SIunits.*;
parameter RotationalDampingConstant d;
Components.Damper damper2(final d=d);
// ...
By adding the final
qualifier, we are indicating that it is no
longer possible to modify the value of damper2.d
. Any
modifications must be made to d
only.
Giving all of the “hard-wired” numerical values in the SMD
model
the same treatment, we would end up with a highly reusable model like
this:
within ModelicaByExample.Components.Rotational.Examples;
model SMD
import Modelica.SIunits.*;
parameter RotationalDampingConstant d1, d2;
parameter RotationalSpringConstant c1, c2;
parameter Inertia J1, J2;
parameter Angle phi1_init=0, phi2_init=0;
parameter AngularVelocity w1_init=0, w2_init=0;
Components.Damper damper2(final d=d2);
Components.Ground ground;
Components.Spring spring2(final c=c2);
Components.Inertia inertia2(
final J=J2,
phi(fixed=true, final start=phi2_init),
w(fixed=true, final start=w2_init));
Components.Damper damper1(final d=d1);
Components.Spring spring1(final c=c1);
Components.Inertia inertia1(
final J=J1,
phi(fixed=true, final start=phi1_init),
w(fixed=true, final start=w1_init));
equation
// ...
end SMD;
If we wanted to use a specific set of parameter values, we could do it
in one of two ways. One way would be to extend the parameterized
model above and include a modification in the extends
statement,
e.g.,
model SpecificSMD
extends SMD(d2=1, c2=5, J2=1,
d1=0.5, c1=11, J1=0.4,
phi1_init=1);
Note that we did not need to include modifications for the values of
phi2_init
, w1_init
and w2_init
, since those parameters were
declared with default values. In general, default values for
parameters should only be used when those defaults are reasonable for
the vast majority of cases. The reason for this is that if a
parameter has no default value most Modelica compilers will generate a
warning alerting you that a value is required. But if a default value
is there, it will silently use the default value. If that default
value is not reasonable or typical, then you will silently introduce
an unreasonable value into your model.
But returning to the topic of propagation, the other approach that
could be used would be to instantiate an instance of the SMD
model
and use modifications on the declared variable to specify parameter
values, e.g.,
SMD mysmd(d2=1, c2=5, J2=1,
d1=0.5, c1=11, J1=0.4,
phi1_init=1);
We’ll defer the discussion on which of these approaches is better until the upcoming chapter on Architectures.