Message Boards Message Boards


Why can't a parameter be used to set the unit-attribute?

Posted 9 days ago
6 Replies
3 Total Likes

Hi everybody,

The following minimal example does compile without any problems in WSM 4.3 and 5.1. But it will cause an error in WSM 12.0 all of a sudden:

model UnitErrorModel
  MyComponent c( hasUnit = "myUnit" );

  block MyComponent
    parameter String hasUnit = "1";
    output Real y( unit = hasUnit );
    y = 10;
  end MyComponent;

end UnitErrorModel;

So the global model will have a component c that modifies a parameter hasUnit which is used by the component to set the unit-attribute of its output y.

In Mathematica [12.0.0 for Microsoft Windows (64-bit) (April 6, 2019)] I observe this:

model = Import[ "" ];
SystemModelSimulate[ model, { 0, 10 } ]


Internal error: Codegen.getValueString: Non-constant expression:c.hasUnit

What has changed in WSM that this is causing an error? Why can't a parameter (note, that making the modification final will not resolve the issue) be used to set the unit-attribute - after all it is known at runtime when compiling the model?

Best regards, Guido

Note: I cross-posted an extended question on StackOverflow.

Background: I am developing a library for (acausal) System Dynamics modeling. Since SD is very low level (e.g. stocks and flows) working with “hard-wired” SI-units is not helpful for modeling managerial or economical problems. Yet, unit checking is very useful and widely embraced in the SD community. Thus, having a flexible way to use parameters to assign units to output (and input) connectors wouldmbe very helpful; this is also how most dedicated SD tools go about it.

6 Replies

While I still cannot find a parameter to be in violation with Modelica specifications (it would be the natural thing to handle this and it has worked so far in WSM and still works in Dymola), changing the declaration for hasUnit from parameter to constant solves the issue!

That at least means, that my library can be rescued with minimal effort ... ;)


You are correct in that it's not in violation with the specification, although making it a constant makes more sense since you would invalidate all your static unit checking if you are allowed to change the unit after building the simulation. We filed an issue on the specification regarding this (


In case you are not aware of it constants wont be visible in the GUI by default, but you can make them visible with the dialog annotation:

model Foo
  constant Real hiddenConstant;
  constant Real visibleConstant annotation(Dialog(group = "GroupName"));
end Foo;

It's also available in the "Add ..." dialog: Add constant dialog

Hello Otto,

Thank you very much for your helpful advice. I was aware of the dialog annotation, but not that it can be nicely accessed via menu.

I still am not totally convinced about constants being better than parameters for units: Modelica allows to have parametric structure, e.g. a component (and its connections) can be turned on or off by a parameter. If you allow the structure of a component to be open to parametric variability wouldn’t by necessity also the units for that components output be having parametric variability?

Having unit checking in place for “apples & oranges” as in SD is imo not always easy - to make this work out quite generally for components is still something I have pushed back with a lower priority. To me components can be build robustly so that indeed the compliance to unit checking is so static that it can be included in the documentation for components. In the end we would simply have to check inputs matching the necessary prerequisites on the level of predefined components?


Edit: The last paragraph is misleading without explanation: Defining a component we may recourse to using abstract units (e.g. “widgets” or “widgets per model time period”). So unit checking could be done one some abstract level (e.g. replace widgets with oranges and continue from there). So the unit checking needed may be done in Mathematica eventually using pattern matching features.

A constant is a parameter that cannot be changed after translation. That is exactly the behaviour in your unit scenario and "parametric structure" scenario. In my opinion it would be better to actually use the constant construct in those scenarios to better communicate what is expected to happen instead of having the compiler force evaluation of the parameter (and there by effectively transform it to a constant).



There is something to your arguments and I am a bit unused (still) to thinking about before and after compilation - not being a software engineer myself... ;-)

To reframe what your are saying, let us simply assume, that I have an exectuable instance of a model and the user can enter a value that is used when the simulation is actually started. On the screen I would have to tell the user an "instance before his entry", that he is supposed to give say a rate in days, weeks, or months - because this is how the model is set up to calculate in the formulas. So, in Modelica lingo the time base of the model (i.e. the unit of time) would have to be of constant variability (e.g. set before the model is made an executable) and the entry of the user would be of parametric variability. Right?

Note: The other option (@Jan Brugard - as with time zones ;-) ) would be to have everything converted to some standard e.g. SI-units like seconds in the case of time. This being very unusual for SD ... I have not done it (yet).

Now, I am still confused about the following code (which is used at the top level of every model I set up with my library):

inner parameter TimeBases modelTimeBase = TimeBases.years "The model's time base";
inner constant String modelTimeBaseUnit = BusinessSimulation.Constants.timeBaseUnits[modelTimeBase];
inner parameter Time dt(unit = modelTimeBaseUnit) = 1 / 16 "Smallest possible interval of time for compatibility with conventional fixed-step System Dynamics models";

I am having an enumeration TimeBases (seconds, minutes, hours, ... ) which is used to choose the unit of time for the model (which then nicely works as a drop down menu). Even though the String modelTimeBaseUnit above is stated to be a constant, it seems to "inherit" the parametric variability of modelTimeBase.

In short: The above use of modelTimeBaseUnit to set the unit attribute inside the lower level components of models does cause an error also.

So, change the above variables to be constants? (or better stick to SI-units with scaling?)



Constants and parameters are very similar, but also have some differences (Section 3.11.2, page 99). Parameters are typically much more common in application models. When in doubt whether to use constant or parameter, use parameter, except when declaring a constant in a package/ library where constant is allowed but not parameter.

Fritzson, Peter. Principles of Object-Oriented Modeling and Simulation with Modelica 3.3: A Cyber-Physical Approach (Kindle-Positionen1795-1799). Wiley. Kindle-Version.

When in doubt ... After thinking about what you have written, I still believe that the user may well choose time and the unit of time as a parameter given a compiled model.

Most Modelica tools support resimulating a model without recompilation after changing a parameter, which usually makes the time waiting for results much shorter.

Fritzson, Peter. Principles of Object-Oriented Modeling and Simulation with Modelica 3.3: A Cyber-Physical Approach (Kindle-Positionen1785-1786). Wiley. Kindle-Version.

Everything in that model could be made to act upon that parametric choice (as with all other parameters also). Chosing the unit of time for giving rates could (and maybe should) well be a parameter of a model (the choice of time scale could be passed onto other components as an inner parameter). While I cannot simply "rescale" apples to be oranges, I can well do so for any unit of time. Where is the fault in my thinking?

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract