如何在Modelica中使用模型中的单元属性?

gwr*_*gwr 2 modelica systemmodeler

动机

Modelica确实存储测量单位(例如,SI单位和非SI单位)作为关于变量的属性.以下是非SI单位的示例:

type Time_months = Real( quantity = "Time", unit = "mo", displayUnit = "months" )
Run Code Online (Sandbox Code Playgroud)

因为对于经济学中的模型而言,在几秒钟内给出速率是相当不利的,我想写一个相当通用的单位转换函数,它将允许转换时间单位.理想情况下,转换为另一个时基的函数应该使用三个输入和一个输出:

input Real timeValue "the value of time to be converted";
input String timeBaseA "the time base for timeValue, e.g. \"mo\" ";
input String timeBaseB "the time base to convert to, e.g. \"yr\" ";
output Real convertedTimeValue "the result of the conversion";
Run Code Online (Sandbox Code Playgroud)

问题

如果我们假设某个时间值的变量已经具有特定的单位属性(例如"mo"),那么在模型中使用该元信息是有意义的.

问题1:如何能像元信息单元模型中进行访问?

理想情况下,以下内容会很棒:

String timeBaseA := timeValue.unit;
Run Code Online (Sandbox Code Playgroud)

要么

String timeBaseA := getUnit( timeValue ) "some function to read unit information";
Run Code Online (Sandbox Code Playgroud)

问题2:如何在一个函数中分配像单位这样的元信息?

在示例中,我们当然希望以正确的时间单位返回输出值.理想情况下,我们希望:

output Real convertedTime( quantity = "Time", unit = strTimeBaseB )
Run Code Online (Sandbox Code Playgroud)

遗憾的是,使用a input会因变异性不同而产生错误:单位属性应具有恒定的可变性,但输入变量具有参数可变性.(使用一个很好的函数 - 也会出于同样的原因失败.)

mar*_*rco 5

关于问题1:

我从未使用Wolfram SystemModeler,但Modelica语言规范3.4在第4.8章(预定义类型和类)中说明:

预定义变量类型(Real,Integer,Boolean,String)的属性不能使用点表示法访问,并且不受公式和算法部分的约束.

关于问题2:

我认为只能从文字或最终参数中定义变量的单位 - 至少这是我在Dymola中观察到的.

替代 - 使用操作员记录

您可以将操作员记录用于您的任务.这将允许您以秒为单位存储时间并将其转换为值使用时所需的时间.

操作员记录允许您定义几个函数来创建它们,比较或添加它们,转换为String等.

请参阅下面的简要示例,其中定义了操作员记录时间,可以使用两个不同的构造函数(秒或天)创建,并且可以将其转换为带有日期或秒的字符串

operator record Time
  Integer s "Second";

  encapsulated operator 'constructor'
    import Time;

    function from_s
      input Integer s "Seconds";
      output Time t(s=s);
    algorithm 
    end from_s;

    function from_d
      input Integer d "Days";
      output Time t(s=d*24*3600);
    algorithm 
    end from_d;
  end 'constructor';

  encapsulated operator 'String' "Convert Time to string"
    import Time;

    function formated
      input Time t;
      input String format = "s" annotation(choices(choice="s" "seconds", choice="d" "days"));
      output String str;

    algorithm 
      if format == "d" then
        str :=String(t.s/24/3600);
      else
        str :=String(t.s);
      end if;
    end formated;
  end 'String';

  encapsulated operator function '==' "Compare time records"
    import Time;
    input Time t1;
    input Time t2;
    output Boolean result "= t1 == t2";
  algorithm 
    result := t1.s == t2.s;
  end '==';

end Time;
Run Code Online (Sandbox Code Playgroud)

用法:

import Modelica.Utilities.Streams.print

t1 = Time(d=12)  // create record using day constructor
t2 = Time(s=3600*24*2)  // create record using second constructor

print(String(t1, format="s"))  // prints 1036800
print(String(t1, format="d"))  // prints 12
print(String(t2, format="s"))  // prints 172800
print(String(t2, format="d"))  // prints 2
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见Modelica规范3.4第14章"重载运算符".

注意:这是使用Dymola 2019测试的,而不是使用Wolfram SystemModeler测试的

  • 对于缩放问题,标称属性是发明的,也许这可能会有所帮助. (2认同)