Message Boards Message Boards

GROUPS:

Unit Checking in System Modeler and making use of unit attributes

Posted 2 months ago
421 Views
|
7 Replies
|
6 Total Likes
|

Unit checking (or dimensional analysis) is an important means of model verification:

Units of Measurement in a Modelica Compiler

Question 1: Is unit checking implemented in the current version of Wolfram System Modeler? (If not, what options are there to achieve it by other means?)

In Modelica units are stored as attributes to variables (e.g. Real( unit = "m/s" ) ) and are usually enabled by modifications of existing basic types with default values for these attributes (e.g. the default unit for the type Real is " ").

Question 2: How to make use of this "meta information" within the model itself:

  • How can I access the unit of some variable?

    parameter String referencedUnit = <function of another variable to access its unit>
    
  • How can I assign such a referenced unit to another variable within the runtime of a model? (e.g. I have written a converter function to convert units of time, say from minutes to months, as this is frequently needed in economic or business simulation models where SIunits are rather an exception).

    output convertedTime =Real( quantity = "Time", unit = <to be assigned in func-body> )
    

    or

    input String timeUnitA; // unit of time to convert from
    input String timeUnitB; //unit of time to convert to
    output convertedTime = Real( quantity = "Time", unit = timeUnitB )
    

(All the above will not work for me as different degrees of variability prohibit this: a modification of the unit attribute must be a constant...).

EDIT: I have cross-posted the second part of my question on stack overflow (5363743)

7 Replies

This answer given on stack overflow suggests that while all time values in Modelica are calculated using "seconds", one may make use of displayUnit (show a derived unit in plots) and nominal (scale values) attributes.

Can a user define his own displayUnit conversions as is possible in Dymola? (displayUnit.mos)

UPDATE:

I checked with WSM 4.3 and there displayUnit will have no effect upon plot outputs, as it seems. I also could not see that using nominal for scaling will work in that version of System Modeler.

Guido,

While all the units of time are done in seconds internally, you can work around this in SystemModeler.

In this model I have a filter that has a one year time constant (talk about moving slowly!). I want to plot it in years, not seconds:

enter image description here

Note that the step starts after one year (which I entered in days in the dialog (display units) but it shows up as seconds on the built-in block. I made my own seconds to year converter block:

model ToYear
  extends Modelica.Blocks.Interfaces.SISO;
equation
  y = u / (3600 * 24 * 365);
  annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5}), graphics = {Text(visible = true, origin = {-135.776, 24.908}, extent = {{-30.776, -3.301}, {30.776, 3.301}}, textString = "Seconds"), Text(visible = true, origin = {118.717, 25}, extent = {{-11.283, -5}, {11.283, 5}}, textString = "Years")}), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 114, 195}, fillColor = {255, 255, 255}, extent = {{-100, -100}, {100, 100}}, radius = 25), Text(visible = true, textColor = {64, 64, 64}, extent = {{-150, 110}, {150, 150}}, textString = "%name"), Text(visible = true, origin = {-147.2, 47.902}, extent = {{-45.346, -12.098}, {45.346, 12.098}}, textString = "Seconds"), Text(visible = true, origin = {140, 45}, extent = {{-33.849, -15}, {33.849, 15}}, textString = "Years")}));
end ToYear;

Now in the Simulation Center do an X-Y plot of toYear1.y vs filter.y

to get

enter image description here

All other units (other than the time base) can be dealt with by using displayunits and doing conversion to your desired unit in Simulation Center. I know you posted about using operator records but I do not see how that will help you in this case (unless I am missing something)

Is this what you were looking for?

Regards,

Neil

Neil,

Thank you for your answer, which is helpful albeit to be honest I am not yet sure whether it resolves akwardness in System Dynamics modeling with Modelica. ;-)

The Block (e.g. continuous time conversion) allows to have some model var to represent time in a time base different from seconds. But I would still have to set up my experiment in seconds, wouldn't I? (e.g. I could not ,say, go from 2018 to 2030 to represent years directly, could I?)

I am not sure about the use of displayUnits as I would need something like conversion factors for units like years and month which I have not seen so far in Version 4.3 which I am trying out here?

So far, my (quick and dirty) solution is to treat my model's time base (years, quarters, months - as rates are usually given in these bases) as if it were seconds and doing numerical conversions for other times bases to my model's time base (using just the dimensionless function output). Then I will just adjust the unit for time in plots manually (or using a simple block as you did) to show the time base.

Guido

PS: Indeed operator records are not really helpful here, albeit the example given on stack overflow is an elegant solution for conversions. So far, I am not aware that you can define your own operator records in WSM though?

Taking the "absence of evidence as evidence of absence" it seems that at the moment System Modeler does not support unit checking (e.g. my first question)?

1) No there isn't any support for unit checking in system modeler, I suppose you could roll your own using Wolfram Language since you can extract the equations and the unit information.

2) If this was allowed (changing the unit dynamically) how would you do the important static unit checking?

SystemModeler has displayUnit support in plots since version 4.3, try for example

model DisplayUnitTest
  extends IntroductoryExamples.MultiDomain.DCMotor(EMF1.i.displayUnit = "mA");
end DisplayUnitTest;

If you plot EMF1.i it will be in mA instead of A. And in the upcoming version you will be able to add your own unit conversions to the list of known units.

But I guess what you want/need in addition to that is "displayUnit" support for the builtin time variable. That is unfortunately not available yet, but as you point out really handy if not a requirement for certain fields.

SystemModeler does support the nominal attribute, but that is used for scaling calculations to improve numeric robustness and not something you see directly as a user.

Thanks again, Otto, for this clarification. I will try out WL/Mathematica for unit checking, but that may be a sobering experience as (imho) unit checking works best for physical models with reusable structure. In System Dynamics (economics/social sciences/ecology) units would be most often "counts" and thus strictly speaking dimensionless. But that would be useless because we sill would not want to mix "apples and oranges" ;-) I am not sure whether have stricter units in this regard may be hindering reuse of structure?

What you are saying about time is "spot-on". Even with time being displayed as years it would be totally akward and maybe numerically unsound to have 5 "units/year" come out as 1.585489e-7... for internal calculations. I am not sure nominal could alleviate this?

Looking at the System Dynamics library by Cellier et al. and the examples there (e.g. World2) show that he doesn't care also: He will give proper units, e.g. Real rate( unit = "units/yr" ) = 5, and then simulates the model as if seconds were years (StartTime = 1900, StopTime = 2100).

You can apply units on a reusable unitless library in different ways

Modify your instances:

model ApplyUnit
  Modelica.Blocks.Sources.Sine sine1(y(unit="m", displayUnit="ft")) annotation(Placement(visible = true, transformation(origin = {-120, 32.607}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
  annotation(Diagram(coordinateSystem(extent = {{-150, -90}, {150, 90}}, preserveAspectRatio = true, initialScale = 0.1, grid = {5, 5})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10}), graphics = {Rectangle(visible = true, lineColor = {0, 114, 195}, fillColor = {255, 255, 255}, extent = {{-100, -100}, {100, 100}}, radius = 25), Text(visible = true, textColor = {64, 64, 64}, extent = {{-150, 110}, {150, 150}}, textString = "%name")}));
end ApplyUnit;

Make specialized classes with units

model DistanceSine
extends Modelica.Blocks.Sources.Sine(y(unit="m", displayUnit="ft"));
end DistanceSine;

However, there isn't any GUI support for setting the initial unit in this way so you have to do it in text mode.

If you are making your own library from ground up you could also make something relying on replaceable/redeclare.

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

Group Abstract Group Abstract