导入物理类型¶
在前面的小节里,我们学会了如何引用其他包中定义的类型。这令开发者不必不断地在自己的局部模型进行重复定义。相反,他们可以将定义放在包内,然后去引用这些软件包。
不过,一遍又一遍地键入冗长的全限定名进行引用不一定十分有趣。因此,Modelica语言包括import
语句,令我们可以方便地使用这些定义,仿佛这些定义是在本模型进行的一样。
再次回忆前面讨论物理类型时的这个例子:
within ModelicaByExample.BasicEquations.CoolingExample;
model NewtonCoolingWithTypes "Cooling example with physical types"
// Types
type Temperature=Real(unit="K", min=0);
type ConvectionCoefficient=Real(unit="W/(m2.K)", min=0);
type Area=Real(unit="m2", min=0);
type Mass=Real(unit="kg", min=0);
type SpecificHeat=Real(unit="J/(K.kg)", min=0);
// Parameters
parameter Temperature T_inf=298.15 "Ambient temperature";
parameter Temperature T0=363.15 "Initial temperature";
parameter ConvectionCoefficient h=0.7 "Convective cooling coefficient";
parameter Area A=1.0 "Surface area";
parameter Mass m=0.1 "Mass of thermal capacitance";
parameter SpecificHeat c_p=1.2 "Specific heat";
// Variables
Temperature T "Temperature";
initial equation
T = T0 "Specify initial value for T";
equation
m*c_p*der(T) = h*A*(T_inf-T) "Newton's law of cooling";
end NewtonCoolingWithTypes;
前面已经介绍了,我们要如何通过使用Modelica标准库内的类型以避免进行本地定义。但是,我们也可以使用import
命令一次性地从Modelica语言标准库中导入这些类型,然后不需输入指定其全限定名而去使用它们。这样代码变为如下:
within ModelicaByExample.PackageExamples;
model NewtonCooling
"Cooling example importing physical types from the Modelica Standard Library"
import Modelica.SIunits.Temperature;
import Modelica.SIunits.Mass;
import Modelica.SIunits.Area;
import ConvectionCoefficient = Modelica.SIunits.CoefficientOfHeatTransfer;
import SpecificHeat = Modelica.SIunits.SpecificHeatCapacity;
// Parameters
parameter Temperature T_inf=300.0 "Ambient temperature";
parameter Temperature T0=280.0 "Initial temperature";
parameter ConvectionCoefficient h=0.7 "Convective cooling coefficient";
parameter Area A=1.0 "Surface area";
parameter Mass m=0.1 "Mass of thermal capacitance";
parameter SpecificHeat c_p=1.2 "Specific heat";
// Variables
Temperature T "Temperature";
initial equation
T = T0 "Specify initial value for T";
equation
m*c_p*der(T) = h*A*(T_inf-T) "Newton's law of cooling";
end NewtonCooling;
在这里,我们将类型定义换成import
语句。注意被高亮行如何等价于以前的代码。让我们仔细观察其中的两个导入语句以了解其对模型的影响。首先观察下面的导入语句:
import Modelica.SIunits.Temperature;
这将类型Modelica.SIunits.Temperature
导入到当前的模型。默认情况下,导入类型的名称会是全限定名最后一项的名称,即Temperature
。这意味着,只要有上述import
语句,我们可以简单地使用类型名Temperature
,而引用将自动转到Modelica.SIunits.Temperature
处。
现在,让我们来看看另一种import
语句:
import ConvectionCoefficient = Modelica.SIunits.CoefficientOfHeatTransfer;
这里的语法有点不同。在这种情况下,我们正在导入的类型是Modelica.SIunits.CoefficientOfHeatTransfer
。但是,相对于直接用全限定名最后一项的名称,即CoefficientOfHeatTransfer
,我们将此类型的本地名称指定为ConvectionCoefficient
。在这里,改变名称允许我们使用在最初几个例子中定义的名称。通过这种方式,我们能够避免重构任何使用了旧名称的代码。另一个指定替代名称(而非Modelica编译器通常指派的默认名称)的原因是为了避免命名冲突。试想,我们希望从两个不同的包导入两种类型,如:
import Modelica.SIunits.Temperature; // Celsius
import ImperialUnits.Temperature; // Fahrenheit
这将使两种名为Temperature
的类型。通过为本地别名定义替代名称,我们进行以下行为:
import DegK = Modelica.SIunits.Temperature; // Kelvin
import DegR = ImperialUnits.Temperature; // Rankine
国际单位
请注意,此示例导入英制单位只是为了演示潜在的命名冲突可能如何发生。但这样做在实践中是非常不好的做法。使用Modelica语言时,用户应该完全使用国际单位,切勿使用任何其他单位系统。如果你想用其他单位来输入数据或显示效果,请使用在 属性小节里讨论的displayUnit
属性。
import
语句最后一个值得讨论的形式是通配符导入语句。一个一个地导入单位可能有些乏味。通配符导入允许我们从给定的包里一次性导入所有类型。回想一下早前的如下例子:
within ModelicaByExample.BasicEquations.RotationalSMD;
model SecondOrderSystem "A second order rotational system"
type Angle=Real(unit="rad");
type AngularVelocity=Real(unit="rad/s");
type Inertia=Real(unit="kg.m2");
type Stiffness=Real(unit="N.m/rad");
type Damping=Real(unit="N.m.s/rad");
parameter Inertia J1=0.4 "Moment of inertia for inertia 1";
parameter Inertia J2=1.0 "Moment of inertia for inertia 2";
parameter Stiffness k1=11 "Spring constant for spring 1";
parameter Stiffness k2=5 "Spring constant for spring 2";
parameter Damping d1=0.2 "Damping for damper 1";
parameter Damping d2=1.0 "Damping for damper 2";
Angle phi1 "Angle for inertia 1";
Angle phi2 "Angle for inertia 2";
AngularVelocity omega1 "Velocity of inertia 1";
AngularVelocity omega2 "Velocity of inertia 2";
initial equation
phi1 = 0;
phi2 = 1;
omega1 = 0;
omega2 = 0;
equation
// Equations for inertia 1
omega1 = der(phi1);
J1*der(omega1) = k1*(phi2-phi1)+d1*der(phi2-phi1);
// Equations for inertia 2
omega2 = der(phi2);
J2*der(omega2) = k1*(phi1-phi2)+d1*der(phi1-phi2)-k2*phi2-d2*der(phi2);
end SecondOrderSystem;
我们可以用导入语句替换这些类型定义,如:
import Modelica.SIunits.Angle;
import Modelica.SIunits.AngularVelocity;
import Modelica.SIunits.Inertia;
import Stiffness = Modelica.SIunits.RotationalSpringConstant;
import Damping = Modelica.SIunits.RotationalDampingConstant;
不过,导入的类型越多,我们需要添加的导入语句就越多。相对地,我们可以将模型写成如下形式:
within ModelicaByExample.PackageExamples;
model SecondOrderSystem
"A second order rotational system importing types from Modelica Standard Library"
import Modelica.SIunits.*;
parameter Angle phi1_init = 0;
parameter Angle phi2_init = 1;
parameter AngularVelocity omega1_init = 0;
parameter AngularVelocity omega2_init = 0;
parameter Inertia J1=0.4;
parameter Inertia J2=1.0;
parameter RotationalSpringConstant k1=11;
parameter RotationalSpringConstant k2=5;
parameter RotationalDampingConstant d1=0.2;
parameter RotationalDampingConstant d2=1.0;
Angle phi1;
Angle phi2;
AngularVelocity omega1;
AngularVelocity omega2;
initial equation
phi1 = phi1_init;
phi2 = phi2_init;
omega1 = omega1_init;
omega2 = omega2_init;
equation
omega1 = der(phi1);
omega2 = der(phi2);
J1*der(omega1) = k1*(phi2-phi1)+d1*der(phi2-phi1);
J2*der(omega2) = k1*(phi1-phi2)+d1*der(phi1-phi2)-k2*phi2-d2*der(phi2);
end SecondOrderSystem;
注意高亮的import
语句。这条(通配符)导入语句从Modelica.SIunits
导入其中的所有定义到当前的模型里。通配符导入语句不能“重命名”类型。导入类型的本地名称将和其在包内的名称一样。
在使用通配符进口之前,请务必阅读这条警告。
在本章里,我们已经看到import
语句如何用于从其他包内导入类型。事实证明,import
语句并非总是那么有用的。当使用图形化建模环境开发模型时,工具一般采用歧义最少、最明确的方法去引用类型:使用全限定名。毕竟,使用图形工具时,名称的长度不会是问题了,用户不再需要输入类型的名称。这也避免了名称查找,命名冲突等问题。