# 外部语言封装规范
# C/C++ 语言封装规范
用户可能采用 C/C++/Fortran/Python 等语言开发的模型,需要集成到本仿真平台中。Modelica 提供了外部函数机制,支持将外部语言开发的模块集成到 Modelica 模型库。
Modelica 中调用外部函数通过 Modelica function 进行,这种 Modelica 函数没有算法区域,取而代之的是外部函数接口声明语句external,以表示调用的是外部函数。
# 外部函数
模型中除了可以调用使用 Modelica 语言编写的函数外,还可以调用其它语言编写的函数,这些其它语言编写的函数称为外部函数。Modelica 中调用外部函数通过 Modelica 函数进行,这种 Modelica 函数没有算法(algorithm)区域,取而代之的是外部函数接口声明语句external,用以表示调用的是外部函数。
package myfuncs
function sin
input Real x;
output Real y;
external "C" ;
end sin;
end myfuncs;
函数myfuncs.sin调用 C 语言函数 sin,调用形式为y=sin(x)。在external中可选地指定外部函数的语言、外部函数调用声明等。
注解用来指定数组布局(arrayLayout)是按行主存储(rowMajor)还是按列主存储(columMajor)、外部函数所需的头文件(Include)、外部函数所需的库文件(Library)、外部函数所需头文件所在的位置(IncludeDirectory)、外部函数所需库文件所在的位置(LibraryDirectory)。
package myfuncs
function exp "e的指数"
input Real u;
output Real y;
external "C" y = exp(u)annotation (Include = "#include\"math.h\"");
end exp;
end myfuncs;
如果没有IncludeDirectory注解,外部函数所需头文件默认位置是包含外部函数的包(package)文件.mo所在文件夹中的Resources/Include子文件夹。同样,若没有 LibraryDirectory 注解,外部函数所需库文件默认位置是包含外部函数的包(package)文件.mo所在文件夹中的Resources/Library子文件夹,不同平台的目标文件还可以存放在相应的平台文件夹中。
支持以下标准平台:
- win32 [32 位 Microsoft Windows]
- win64 [64 位 Microsoft Windows]
- Linux32 [Intel 32 位 Linux]
- Linux64 [Intel 64 位 Linux]
# Modelica 模式 URI
Modelica 模式 URI 用于表示 Modelica 资源所在的位置,其形式如下:
modelica://[LibraryName]/[Path]
URI 由三部分组成:modelica://是 Modelica 模式 URI 的专用标识,跟在其后两部分为LibraryName跟Path:LibraryName表示 Modelica 包的全名,path 部分用于表示资源相对于包的位置,是相对路径。如果LibraryName中有Q-IDENT,则所有 URI 保留的字符都遵循 URI 表示的规则,即百分号编码。示例:
LibraryName:Modelica.Mechanics,Path:Src/Include,如下所示:
modelica://Modelica.Mechanics/Src/Include
LibraryName:myRec.'+',Path:Lib,如下所示:
modelica://myRec.%27%2b%27/Lib
# Include 和 IncludeDirectory 注解
Include 注解中的内容直接嵌入至模型 C 代码中,因此,其中可以指定包含文件或者直接写一段 C 代码。
指定包含文件:
function exp "Exponential, base e"
input Real u;
output Real y;
external "C" y = exp(u) annotation(Include="#include \"math.h\"");
end exp;
直接嵌入 C 代码:
function IncTest1
input Real x;
output Real y;
external "C" y=myDouble(x) annotation(Include="double myDouble(double x)
{return 2*x;}");
end IncTest1;
IncludeDirectory 注解指定包含文件所在的位置,以 URI 的 Modelica 模式表示。
# Library 和 LibraryDirectory 注解
Modelica 中外部函数声明时用 Library 注解指定链接库名(不带扩展名)。下面示例中指定的连接库名是 Fac,那么完整的连接库名称是Fac.lib(vc 编译生成)或libFac.a(gcc 编译生成)。
function Fac "factorial"
input Integer n;
output Real res;
external "C" annotation (Library = "Fac",
LibraryDirectory="modelica://ExternFuncUseDll.ExternFunc");
end Fac;
LibraryDirectory 注解指定库文件和dll(或so)文件所在的位置。指定位置中可以使用不同的平台文件夹存放各平台的库文件和dll(或so)文件,:
- win32 [32 位Microsoft Windows]
- win64 [64 位Microsoft Windows]
- Linux32 [Intel 32 位 Linux]
- Linux64 [Intel 64 位 Linux]
# Julia 函数库集成规范
本节说明如何将科学计算环境中开发的 Julia 函数库封装为 Modelica 函数库中的模块,以支持用户在系统仿真环境中重用 Julia 函数库,并以图形化的方式集成科学计算函数或模型。
# Syslab Function 开发规范
Syslab Function 是一种将 Julia 函数封装为 Modelica 模型的机制。Syslab Function 通过 Modelica 外部函数实现。本节说明 Syslab Funtion 的功能机制和操作步骤。 Syslab Function 包含两个模型:
- SyslabGlobalConfig:用于全局声明,包括导入包及全局变量声明等。
- SyslabFunction:用于嵌入 Julia 函数,并将 Syslab Function 模块的输入和输出数据指定为参数和返回值。
# SyslabGlobalConfig
SyslabGlobalConfig 用于为系统中的 Julia 函数提供全局声明,例如导入包或声明全局变量。当创建了 SyslabGlobalConfig 组件之后,单击右键菜单中的 Syslab 初始化配置...,可以在 Syslab 中打开编辑器,编写全局声明的 Julia 脚本。
# SyslabFunction
SyslabFunction用于嵌入 Julia 函数,并将 Syslab Function 模块的输入和输出数据指定为参数和返回值。系统仿真每推进一步都会调用该 Julia 函数。
对于SyslabFunction组件而言,单击右键菜单中的编辑 Syslab 脚本函数...,可以在 Syslab 中打开编辑器,编写 Julia 脚本,例如:
上图中的 Julia 脚本即完成了一个 Syslab Function 定义,组件将生成一个名为 in_t 输入端口和两个分别名为 out_x、out_y 的输出端口。
SyslabFunction组件认为脚本中的第一个函数为本组件的主函数,其他函数均为服务于主函数的辅助函数。根据主函数的内容,组件从函数声明中的输入参数中,获取组件的输入端口的数量及名称;从返回值语句中获取组件的输出端口的数量及名称。Syslab 的主函数的定义规则如下:
- 模型的输入端口数量由 Julia 函数的声明决定,类型和维度在端口由用户在设置对话框中指定;
- 模型的输出端口数量由 Julia 函数的返回值决定,类型和维度在端口由用户在设置对话框中指定;
- 端口类型支持实型、整型、布尔型,维度字段如果空缺,则认为端口为标量端口;
- 主函数必须使用 function 定义;
- 主函数的输入不要指定类型,不要指定具名参数;
- 主函数的输出必须使用 return 指定,且必须为函数体中已经出现的变量符号;
- 在同一个系统模型中,函数名必须是唯一的。
# Syslab Object 开发规范
Syslab Object 是一种 Julia 类,具有用于算法建模的特定方法和属性。System object 适用于为动态系统建模和处理流式数据。用户可以使用模型库产品中包含的预定义 Syslab Object,也可以定义自己的 Syslab Object。
Syslab Object Block 是系统建模环境将 Syslab Object 封装成的 Mo 模块,提供了一套结构化的模板流程,可在执行期间自动完成许多管理操作,包括初始化系统、验证数据、单步计算和终止等操作。
Syslab Object 的组件关系如下图所示:
# Syslab Object 的开发规范
Syslab Object 是一个 Julia 类,包含类名、类属性、类方法等基本要素。Syslab Object 的开发需要遵循具体的开发规范,其模板文件如下所示:
using ObjectOriented
@oodef mutable struct Untitled
# Description (用于生成Modelica组件描述)
# Template for syslab object block.
# Parameter (用于生成 Modelica 组件参数,包括名称、类型、描述)
# 格式:参数名::参数类型 = 参数值 # 参数注释
# 例如:
gain::Real = 1.0 # 增益
# Private (Julia内部变量)
# 格式:变量名::类型 = 值 # 变量说明
# 例如:
_count::Integer = -1 # 计数器
# Methods (主要调用算法,包括setupImpl,stepImpl,releaseImpl)
# 初始化函数:函数名固定,函数形参与stepImpl函数形参一致
function setupImpl(self, u)
self._count = 0
# ...
return nothing
end #setupImpl
# 单步计算函数:函数名固定,第一个函数形参必须是self,其余函数形参将作为Modelica组件的输入端口,函数返回值作为输出端口
function stepImpl(self, u)
self._count += 1
# ...
y = u * self.gain
return y
end #stepImpl
# 释放资源函数:函数名固定,且只能有一个函数参数self
function releaseImpl(self)
# ...
return nothing
end #releaseImpl
# 其它自定义函数,第一个函数形参数必须是self
# function xx(self)
# ...
# end
end
编辑 Julia 对象文件时,请注意以下几点
- 请勿删除注释标签,如 # Description、# Methods 等;
- 请勿删除初始化函数
setupImpl(),单步计算函数stepImpl(),释放资源函数releaseImpl(); - 类名需要具有唯一性,且与文件名一致。
属性
Julia 对象文件中属性分为公共属性 Parameter 和私有属性 Private。属性对应的规则如下表所示:
| 属性分类 | 特点 | 支持的数据类型 |
|---|---|---|
| Parameter | Sysplorer 中可以直接访问 | 特定的 Julia 数据类型 |
| Private | 只能通过 Syslab Object 的方法来访问,用户不可见 | 符合 Julia 语法的所有数据类型 |
可以在Parameter参数中使用以下数据类型:
| String | Bool | Int64 | Integer | Float64 | Real |
|---|---|---|---|---|---|
| Number | Vector{Int64} | Vector{Integer} | Vector{Float64} | Vector{Real} | Vector{Number} |
| Matrix{Int64} | Matrix{Integer} | Matrix{Float64} | Matrix{Real} | Matrix{Number} | / |
方法
Julia 对象文件中包含有三个固定方法:
| 方法 | 说明 |
|---|---|
| setupImpl | 执行设置和初始化任务 |
| stepImpl | 系统输出和状态更新方程 |
| releaseImpl | 释放使用的资源和执行必要的清理任务 |
setupImpl
初始化 Syslab Block。
- 语法
function setupImpl(self, input1, input2, ...)
# ...
return nothing
end #setupImpl
- 说明
setupImpl 使用一个或多个输入对 Syslab Block 进行初始化和设置,仿真过程中仅运行一次。
- 示例
此示例说明如何使用 setupImpl 的输入参数 u 初始化内部变量 _count。setupImpl 的返回值必须为 nothing。
function setupImpl(self, u)
self._count = size(u, 2)
return nothing
end #setupImpl
stepImpl
系统输出和状态更新方程。
- 语法
function stepImpl(self, input1, input2, ...)
# ...
return output, output2, ...
end #stepImpl
- 说明
stepImpl 指定运行 Syslab Object 时要执行的算法,运行对象时将会使用输入参数、属性和状态更新方程来计算输出并更新对象的状态值。
- 示例
此示例说明使用 stepImpl 方法在每一步仿真时将输入参数值均增加 1。
function stepImpl(self, x1, x2)
y1 = x1 + 1
y1 = x2 + 1
return y1, y1
end #stepImpl
releaseImpl
释放资源。
- 语法
function releaseImpl(self)
# ...
return nothing
end #releaseImpl
- 说明
releaseImpl 会释放 Syslab Object 使用的资源,例如文件句柄或设备,以及执行任何必要的清理任务。
- 示例
此示例说明使用 releaseImpl 方法关闭 Syslab Object 打开的文件。
function releaseImpl(self)
fclose(self._fileID);
return nothing
end #releaseImpl
# Syslab Object Block 的开发规范
可以按照下图所示的流程,在系统建模仿真环境中开发 Syslab Object Block。
- 加载模型库:在 Syslab 中启动 Sysplorer,加载 SyslabWorkspace 模型库
- 创建单个组件:拖拽创建单个 Syslab Object 组件
- 配置组件:关联组件对应的 Julia 对象文件
- 新建或编辑 Syslab Object 组件的 Julia 对象文件
- 编辑 Syslab Object 组件的端口设置
- 将组件组合到系统中: 编写一个包含这些 Syslab Object 的 Sysplorer 程序,完成其余部分模型的建模
- 运行系统:在 Sysplorer 中运行您的程序进行仿真
- 修改组件:对已关联 Julia 对象文件的组件进行修改
# 加载模型库
请通过 Syslab 启动 Sysplorer 软件,确认插件管理中已启用 Syslab Extension for Sysplorer 插件(默认启用)之后,加载 SyslabWorkspace 模型库。
# 创建单个组件
通过拖拽创建单个 SyslabObject 组件。除了工具箱提供的 Syslab Object 以外,您还可以创建自定义的 Syslab Object,组件在模型库中的路径为SyslabWorkspace.SyslabObject.SyslabObject。
# 配置组件
如果您使用某个工具箱中提供的 SyslabObject 组件,可编辑修改默认属性值和方法以便为您的特定系统建立模型。
如果您需要配置自定义 System Object:
单击右键菜单中的选择 Syslab 对象文件…,弹出 Syslab 对象参数对话框。

- 如果您需要新建 Julia 对象文件,单击对话框中新建按钮,可以在 Syslab 中打开编辑器并默认新建一个 Julia 对象文件;您也可以通过 Syslab 的主页菜单栏中的新建下拉框中选择新建 Julia 对象进行创建:
- 编辑 Julia 对象文件;
- 保存 Julia 文件,默认类名为 Untitled,请注意文件名需与类名一致,保存后此文件自动关联到
SyslabObject组件; - 如果您需要将
SyslabObject组件关联到现有 Julia 对象文件,单击对话框中的 浏览… 按钮选择对应的 Julia 文件。您也可在文本框中输入文件路径,文件路径支持绝对路径和相对路径; - 单击对话框中的确认按钮,组件依据 Julia 文件自动生成参数、端口等信息。
提示
组件的默认参数、端口信息仅在单击确认按钮后进行刷新。如您对 Julia 文件进行了修改,请重新单击确认按钮。
单击右键菜单中的设置 Syslab 对象端口… 项,弹出设置 Syslab 函数端口对话框:
- 指定输入/输出端口的类型和维度信息;
- 如有需要,可修改输入端口的范围、初值和参数说明的信息。
# 将组件组合到系统中
当您确定了所需组件并已创建和配置 Syslab Object 之后,请组装您的系统。
# 运行系统
单击 Sysplorer 的仿真按钮对系统进行仿真。如果您需要在 Sysplorer 中获取 Syslab Block 的调试信息,请参阅调试信息。
# 修改组件
如果您需要修改已关联 Julia 文件的 SyslabObject 组件配置,请选中组件后,单击右键菜单中的选择 Syslab 对象文件… 项,单击弹出对话框中的源代码按钮,可在 Syslab 中打开对应文件进行编辑。
完成编辑后,单击对话框中的确认按钮,组件将自动更新参数、端口等信息。
对于组件参数,如果已在 Sysplorer 中对类生成的属性初始值进行了修改,比如在 Sysplorer 组件参数底部停靠栏中修改了初始属性值, 更新后不会覆盖当前修改值。
对于组件端口,如果您删除了某一端口,更新后对应位置上的原有连接线将悬空。
您也可以在对话框中新建或更改关联的 Julia 对象文件,组件将自动更新。