# 外部语言封装规范
封装外部语言模型库的过程中需要遵循相应的封装规范,以确保外部语言模型库在 Syslab 平台中的正常运行。
# 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 | 释放使用的资源和执行必要的清理任务 |
# Syslab Object Block 的开发规范
可以按照下图所示的流程,在系统建模仿真环境中开发 Syslab Object Block。
- 加载模型库:在 Syslab 中启动 Sysplorer,加载 SyslabWorkspace 模型库;
- 创建单个组件:拖拽创建单个 Syslab Object 组件;
- 配置组件:关联组件对应的 Julia 对象文件;
- 新建或编辑 Syslab Object 组件的 Julia 对象文件;
- 编辑 Syslab Object 组件的端口设置。
- 将组件组合到系统中: 编写一个包含这些 Syslab Object 的 Sysplorer 程序,完成其余部分模型的建模;
- 运行系统:在 Sysplorer 中运行您的程序进行仿真;
- 修改组件:对已关联 Julia 对象文件的组件进行修改。