组织内容¶
让我们先来简单地演示如何将内容组织成包。要做到这一点,我们将重温经典猎食者猎物系统模型。在我们前述的模型中,所有的变量类型均是Real
。让我们来优化模型中一系列不同量的类型。
我们可以将这些类型组织成如下的包:
package Types
type Rabbits = Real(quantity="Rabbits", min=0);
type Wolves = Real(quantity="Wolves", min=0);
type RabbitReproduction = Real(quantity="Rabbit Reproduction", min=0);
type RabbitFatalities = Real(quantity="Rabbit Fatalities", min=0);
type WolfReproduction = Real(quantity="Wolf Reproduction", min=0);
type WolfFatalities = Real(quantity="Wolf Fatalities", min=0);
end Types;
对于这段Modelica代码,需要注意的第一件事情是,它使用了package
关键字。定义package
的语法与定义model
或function
的语法非常相似。而它们的主要区别在于package
内仅包含定义或常量。package
定义除了constant
量外不能包含任何变量声明。在本例,我们看到这个package
只包含type
的定义。
现在,让我们把注意力转向Lotka-Volterra模型本身。假设此模型自身不需要定义类型,而去依赖于我们刚才定义的类型,模型可以被重构如下:
model LotkaVolterra "Lotka-Volterra with types"
parameter Types.RabbitReproduction alpha=0.1;
parameter Types.RabbitFatalities beta=0.02;
parameter Types.WolfReproduction gamma=0.4;
parameter Types.WolfFatalities delta=0.02;
parameter Types.Rabbits x0=10;
parameter Types.Wolves y0=10;
Types.Rabbits x(start=x0);
Types.Wolves y(start=y0);
equation
der(x) = x*(alpha-beta*y);
der(y) = -y*(gamma-delta*x);
end LotkaVolterra;
请注意,现在所有的参数和变量如何得到一个特定类型(而不仅仅是普通的Real
类型)。相反,我们能够将变量和附加信息相关联,而不局限于其为连续变量这一事实。例如,通过在类型定义加入min=0
这一修饰符,我们可以规定变量非负。
仅通过观察Lotka-Volterra模型,我们很难发现模型在哪里找到上述的类型定义。Modelica编译器会使用一系列查找规则来查找上述定义。在后面我们将会介绍查找规则。就目前而言重要的一点是,我们有引用模型外数据的能力。
让我们稍稍离开目前的主题,去看看关于组织的一些额外细节。前述的Types
包以及对其进行引用的LotkaVolterra
模型均是一个称为NestedPackages
的包的一部分。NestedPackages
的定义如下:
within ModelicaByExample.PackageExamples;
package NestedPackages
"An example of how packages can be used to organize things"
package Types
type Rabbits = Real(quantity="Rabbits", min=0);
type Wolves = Real(quantity="Wolves", min=0);
type RabbitReproduction = Real(quantity="Rabbit Reproduction", min=0);
type RabbitFatalities = Real(quantity="Rabbit Fatalities", min=0);
type WolfReproduction = Real(quantity="Wolf Reproduction", min=0);
type WolfFatalities = Real(quantity="Wolf Fatalities", min=0);
end Types;
model LotkaVolterra "Lotka-Volterra with types"
parameter Types.RabbitReproduction alpha=0.1;
parameter Types.RabbitFatalities beta=0.02;
parameter Types.WolfReproduction gamma=0.4;
parameter Types.WolfFatalities delta=0.02;
parameter Types.Rabbits x0=10;
parameter Types.Wolves y0=10;
Types.Rabbits x(start=x0);
Types.Wolves y(start=y0);
equation
der(x) = x*(alpha-beta*y);
der(y) = -y*(gamma-delta*x);
end LotkaVolterra;
end NestedPackages;
需要注意,关于NestedPackages
包一个非常重要的点是,它是包含在另一个名为PackageExamples
的包内。而PackageExamples
则又是一个名为ModelicaByExample
的包的一部分。由顶部的within
子句我们便可以发现这点:
within ModelicaByExample.PackageExamples;
在这本书至今模拟过的每一个模型均是包含在包内的。而在展示那些例子的源代码时,我们都将首行隐藏了起来。原因是当时我们还没有准备好讨论within
子句的作用。但within
子句在那些例子中均是存在的。
注意,Types
包以及LotkaVolterra
模型并没有任何的within
子句。原因是由于它们均是直接定义在NestedPackages
包内,因而我们知道它们具体在什么包内。那么,为什么这个子句会直接出现在NestedPackages
的定义之前呢?这是因为NestedPackages
是个独立的文件。换言之,Modelica定义映射到文件和目录时,我们需要明确指定定义之间的关系。我们将在后面讨论的文件、目录和包的定义之间的关系。暂时而言,重要的是了解within
子句仅用于指定文件所从属的父包。