引脚的数量已经扩展到 10 个进口和 10 个出口。如何使用这些引脚,取决于 DLL 的编程。
管道连接 |
||
1 |
进口 1 |
|
2 |
进口 2 |
|
3 |
进口 3 |
|
4 |
进口 4 |
|
5 |
进口 5 |
|
6 |
进口 6 |
|
7 |
出口 1 |
|
8 |
出口 2 |
|
9 |
出口 3 |
|
10 |
出口 4 |
|
11 |
出口 5 |
|
12 |
出口 6 |
|
13 |
出口 7 |
|
14 |
出口 8 |
|
15 |
出口 9 |
|
16 |
出口 10 |
|
17 |
进口 7 |
|
18 |
进口 8 |
|
19 |
进口 9 |
|
20 |
进口 10 |
组件 65 可以链接到用户的自定义计算程序,实现在 EBSILON 中自定义计算组件的功能。自定义计算程序与组件 65 的链接以 DLL 形式实现。必须有合适的开发工具来创建这样一个DLL。
调用 DLL 时,与相应组件相关的数据会从 Ebsilon 模型转移到这个 DLL,完成自定义计算过程后,将计算结果返回到 EBSILON。
使用该组件,可像组件 93(内核脚本)一样,触发方程式。为此,需要使用到"扩展接口"和 C++ 编程。
组件调用的 DLL 文件路径可以直接在组件中指定,这样可以在一个模型中使用不同的 DLL。之前,这只能在常规设置中实现,对所有模型和组件有效。
"端口"标签窗口显示了分配给组件连接器的流体类型。
每个连接器都有一个条目,包括连接器编号和一个组合框,显示当前分配的流体类型。
通过点击组合框中的流体类型可以从显示的列表中选择改变流体类型。
通过指定"无"作为流体,可以完全隐藏链接。
注意:
这些组件也有特征线、结果数组、规格矩阵和结果矩阵。可以在每个迭代步骤中计算出结果值。参见标签"计算"->"计算选项"->"结果计算"->(1)"在每个迭代步中计算结果"。
对于组件 65 有额外的接口。参见"专家"选项卡和"编辑组件"一章的注释->"专家"选项卡。
DLLPATH |
可编程 Dll 的替代路径 这个条目是可选的。如果这里没有指定路径,路径将从通用选项中获取。 |
FSEQ |
调用序列中的位置 如父工况(子工况为可选项) 表达式 =0: 与其它组件平行 =1: 较晚,在流体被重新计算之后 |
FTAKEOVERNOMINALVALUES |
接管标称值 : 在成功的(局部)部分功率计算之后,根据这个特定的值决定是否采用 SPEC1, ..., SPEC80 的值作为标称值。 如父工况(子工况为可选项) 表达式 = 0: 调用函数 XUI_hasNominalValues 并根据结果进行处理 = 1: 在设计模式下,是;在部分负荷模式下,否 = 2: 是 (采用标称值) = 3: 否 (不采用标称值) = 4: 使用别名"FMODE"的值:=0 -> 全局;>0 -> 否/局部部分负荷;<0 -> 是/局部解释 |
FPROG |
程序 - ID(用户指定的组件子类型分类) |
SPEC1,..., SPEC80 |
用户定义的规格值(也可作为标称值) |
一般来说,所有的输入需要可见。通常会提供默认值。
更多关于输入域的颜色和描述的信息,请参见编辑组件\规格值。
关于设计值与非设计值以及标称值的更多信息,请参见通用\接受标称值。
要在 C/C++ 中创建一个程序,需要一个单独的 C/C++ 编译器,它生成一个动态链接库(DLL),来替代 DLL Programmable.dll。这个 DLL 需要与 EBSILONProfessional 一起使用(用 Visual C++ 6.0 编译和链接),以便用这个组件进行计算。
可以实现几种类型的自定义组件,然后用规格值 FPROG 来区分。这个值决定了使用哪种类型。由于 Programmable.DLL 只可用一次,每种类型都可以在模型或循环中使用。
Programmable.dll 被 Ebsilon 计算内核使用,而不是被图形用户界面使用(例如,为了与界面交换数据,可以使用 EbsOpen)。它在求解过程中的每个迭代步骤中被调用,因此是迭代过程的一部分。因此,DLL具有适当的收敛性是很重要的。否则,计算将需要更多的迭代步骤或根本无法收敛。
计算内核通过头文件 EbsUser.h 和 xui.h 中描述的接口调用 DLL,这些文件可以在 Examples\xui_dll 目录中找到。
C 语言的 DLL 接口由一个名为 EbsUser_Comp65 的单一函数组成。这个函数的返回值是一个整数,可以根据需要进行设置。计算内核对这个返回值的解释如下:
C++ 的 DLL 接口由几个函数组成,它们的名字都以"XUI_"开头。这些函数的描述包含在头文件 EbsUser.h 和 xui.h 中(只有英文版本)。
如果出现错误或警告,返回值会显示在错误分析窗口。
函数 EbsUser_Comp65 的唯一参数是一个指向 EBSPROG_CALC_DATA 结构的指针。这个结构被定义为
typedef struct {
int compno; // 组件编号 (1 = 图纸中第一个65号组件; 2 = 第二个65号组件 ...)
int nrule; // 要计算的规则数 (= 第一个规格值)
int nspecs; // 规格值的数量
int nresults; // 规格值的数量
int n_inlines; // 输入管道的数量
int n_outlines; // 输出管道的数量
int n_materials; // 一个管道组份中的最多材料数
EBSPROG_PARAMS calcparams; // 计算参数
double *specs; // 'nspecs'组件规格值的数组
// 空白值表示为'-999'
double *results; // 'nresults'组件结果值数组
EBSPROG_LINEVAL *in; // 'n_inlines'输入管道值的数组
EBSPROG_LINEVAL *out; // 'n_outlines'输出管道值的数组
} EBSPROG_CALC_DATA;
在 Ebsilon 计算内核调用 DLL 之前,创建了上面的结构并将实际迭代步骤中的数据复制到这个结构中。因此,在 DLL 中可以访问该结构中的所有这些数据。
参见 EbsUser.c 中的示例,如何访问 Ebsilon 规格值和管道值,并指定结果。
参数 compno 表示目前正在被计算的组件 65(循环中可能有多个)。
参数 nrule 与属性窗口中的规范值 FPROG 定义的值相同。如果想实现多个用户定义组件,这可以用来区分不同类型的用户定义组件。
参数 nspecs、nresults、n_inlines、n_outlines 和 n_materials 表示相应数组的大小。在代码中应该总是使用这些量而不是固定的数字(如 39,40,6),因为在未来的 Ebsilon 版本中,这些数字可能会改变。
EBSPROG_PARAMS 是用于指定计算条件和设置的结构:
typedef struct {
int mode; // 调用模式:初始化 (1), 计算 (2), 完成 (3)
// 模式 1:从 Ebsilon 接收规格数据并执行初始化
// 没有数据传输回 Ebsilon
// 模式 2:从 Ebsilon 接收管道数据并执行计算
// 结果被传回 Ebsilon
// 模式 3:规格值和组件结果被传回 Ebsilon
int itno; // 迭代步数(可能从 1 到 998 不等)
int design; // 设计(0)/非设计(1)计算
int wst; // 要使用的水蒸汽表: 0=IFC-67, 1=IAPWS-IF97
} EBSPROG_PARAMS;
如果程序需要进行某些初始化或结束工作,如分配和删除内存或打开和关闭文件,可以通过程序使用模式参数。
参数 itno 代表目前正在执行的迭代步骤。
参数 design 很重要,有两个原因:
如果调用材料表,就需要 wst 参数。出于一致性的考虑,必须在 DLL 中使用与 Ebsilon 中相同的水/蒸汽表的表述。
EBSPROG_LINEVAL 是一个包含管道值的结构。对于输入管道,这些值由 Ebsilon 计算提供。对于输出管道,Ebsilon 期待这些值由程序计算得出。
typedef struct {
double p; // 压力[bar]
double h; // 焓[kJ/kg]
double m; // 质量流量[kg/s]
double ncv; // 净热值[kJ/kg]
MT_ANALYSE ana; // 组份
double fugit; // 逃逸部分(仅限于煤)
double rho; // 密度 (仅限于油类)
double zfac; // Z 因子 (仅限于油类)
int fcoal; // 煤的类型 (只限于煤)
} EBSPROG_LINEVAL;
MT_ANAYLSE 结构用于指定材料组份,在 material_table.h.中定义,详见材料表函数的描述。
用户须定义,6 个出口连接的值如何依赖于 6 个进口连接的输入值。
如果需要超过 6 条进口管道和 6 条出口管道,可以把几个组件组合起来(由参数 FPROG 区分)。可以从 C 程序中调用所有的材料表函数(水和燃烧)。
可以从 C 程序中调用所有的材料表函数(水和燃烧)。
通过修改 Make-file 和包括额外的头文件,可轻松地整合任何其它程序或 API。
请注意,应用的计算在模拟的每个迭代步骤中进行,并且对收敛行为有影响。
文件可能包括几个类型为 65 的组件。每个组件都必须分配一个有效的子组件编号 FPROG。每个分配的子组件编号(FPROG)必须分别在 C 代码或 DLL 中应用。
在"Data\Examples\Programmable\ebsuser.c"中给出了三个子组件的示例。这些示例已经用 Microsoft Developer Studio 6.0(Visual C++)进行了测试。与之相关的文件存储在 EBSILONProfessional 安装目录下的 data\examples\components\ 中。名字为 Component_65.ebs、Component_65_2.ebs 和 Component_65_3.ebs。
利用 EBSILONProfessional 提供的 ebsuser.c 文件。在修改该文件之前,通过编译和连接这个原始文件,可创建用户自己的 DLL Programmable.dll。
如下:文件
一起存储在 EBSILONProfessionalinstallation 安装目录的 Examples\Programmable\ 中。
如果安装了 Visual C++, 须
ebsuser.obj 和 DLL ProgrammableUser.dll 将被创建。
通过重新命名和复制将 EBSILONProfessional 提供的 Programmable.dll 替换为刚刚创建的 DLL。不要忘记备份原始的 DLL,以防创建的 DLL 不能工作。
要应用用户自己的子组件,须修改 ebsuser.c 中的函数 EbsUser_Comp65。这个函数如下:
LINKDLL int EbsUser_Comp65 (EBSPROG_CALC_DATA *data)
{
int rc;
switch (data->nrule) {
case 1:
..... code for sub type 1
break;
case 2:
..... code for sub type 2
break;
case 3:
..... code for sub type 3
break;
default:
rc = -999;
break;
}
return rc;
}
添加一个子组件意味着添加一个带有开关(FPROG)的新 "case"。可用的输入为:
每个参数包括所有六个输入管道的值。
作为示例,EBSILONProfessional 附带的 ebsuser.c 包括三个子组件(FPROG 1、2 和 3)。
第一个例子(FPROG = 1)使用所有的输入和输出管道。它是位于EBSILONProfessional 安装目录 examples\components\ 下的 Component_65.ebs。
第二个例子(FPROG = 2)(详细描述)使用输入管道 5 和 6 以及输出管道 2 和 3。它是位于EBSILONProfessional 安装目录 examples\components\ 下的 Component_65_2.ebs。这个例子中使用了材料表的接口,但只使用了水表。
第三个例子(FPROG = 3)(Component_65_3.ebs 位于安装目录的 examples\components\ 中)将一个粗煤气质量流分成三个质量流:
在这个例子中使用了燃烧材料表的接口,计算产生的质量流的净热值。
可以使用和修改 EBSILONProfessional 附带的 make 文件(Data\Examples\Programmable\Programmable.mak)。可以使用用户自己的编译器、链接器、make 文件等 或 任何其它需要的工具。
创建的 DLL 必须是一个多线程的 DLL。请不要使用 MFC。
可用的函数如下。当调用函数时,输入值必须如下指定。
使用的缩写是
缩写 |
英语 / 中文 |
德文 |
蒸汽 |
|
|
p |
pressure / 压力 |
Druck |
T |
temperature / 温度 |
Temperatur |
h |
specific enthalpy / 比焓 |
spezifische Enthalpie |
s |
specific entropy / 比熵 |
spezifische Entropie |
v |
specific volume / 比容 |
spezifisches Volumen |
cp |
isobaric specific heat / 等温线比热 |
Isobare spezifische Wärmekapazität |
x |
quality / 质量 |
Dampfgehalt |
烟气 |
|
|
p |
pressure / 压力 |
Druck |
T |
temperature / 温度 |
Temperatur |
h |
specific enthalpy / 比焓 |
Spezifische Enthalpie |
s |
specific entropy / 比熵 |
Spezifische Entropie |
v |
specific volume / 比容 |
Spezifisches Volumen |
cp |
isobaric specific heat / 等温线比热 |
Isobare spezifische Wärmekapazität |
x |
water content / 水含量 |
Wassergehalt |
xs |
saturation water ratio / 饱和水比率 |
Maximum Steam Fraction (Saturated) |
MRAT |
mass ratios / 质量比率 |
Mass Fraction |
VRAT |
volume ratio / 体积比率 |
Volume Fraction |
MG |
molar weight / 摩尔比重 |
Molgewicht |
HU |
lower calorific heating value / 低热值 |
unterer Heizwert |
结果► |
比焓 |
压力 |
比熵 |
温度 |
比容 |
等温线比热 |
蒸汽含量 |
输入▼ |
|||||||
压力,温度 |
h = f (p, T) |
|
s = f (p, T) |
|
v = f (p, T) |
|
|
压力,比焓 |
|
|
s = f (p, h) |
T = f (p, h) |
v = f (p, h) |
cp = f (p, h) |
x = f (p, h) |
压力,比熵 |
h = f (p, s) |
|
|
T = f (p, s) |
|
|
|
温度 |
|
p = f (T) |
|
|
|
|
|
比熵 |
|
p = f (s) |
|
|
|
|
|
比熵 |
|
p = f (h) |
|
|
|
|
|
压力 |
h = f (p) h = f (p) |
|
|
T = f (p) |
|
|
|
液体可以由各种物质组成。必须指定各个物质的质量份数。
除了表格中规定的输入值外,几乎所有的计算都需要这些质量份数。只有质量份数的计算本身需要体积份数。
结果► |
比焓 |
比熵 |
温度 |
比容 |
比热 |
流体水份额 |
饱和水比率 |
体积比率 |
质量比率 |
净热值 |
摩尔比重 |
输入▼ |
|||||||||||
压力,温度 |
h = f (p, T) |
s = f (p, T) |
|
v = f (p, T) |
cp = f (p, T) |
x = f (p, T) |
xs = f (p, T) |
|
|
|
|
压力,比焓 |
|
s = f (p, h) |
T = f (p, h) |
|
cp = f (p, h) |
x = f (p, h) |
|
|
|
|
|
压力,比熵 |
h = f (p, s) |
|
T = f (p, s) |
|
|
|
|
|
|
|
|
只有质量比率 |
|
|
|
|
|
|
|
VRAT |
MRAT |
HU |
MG |
结果► |
比焓 |
温度 |
比热 |
净热值 |
输入▼ |
||||
压力,温度 |
h = f (p, T) |
|
cp = f (p, T) |
|
压力,比焓 |
|
T = f (p, h) |
cp = f (p, h) |
|
只有质量比率 |
|
|
|
Hu |
燃料和烟气可以由几种材料组成。这些材料的质量比必须被定义。
除了上表中规定的输入值外,几乎所有的计算也需要这些质量比。只有质量比计算本身需要体积比。
要定义一个组份,只需使用函数 mt_init_analyse () 和 mt_set_analyse ():
void mt_init_analyse (MT_ANALYSE *分析,
MT_ANALYSE_TYPE 分析_id);
BOOL mt_set_analyse (MT_ANALYSE *分析,
MT_ANALYSE_PART 组件_id,
double 份额);
要查询一个组份,只需调用 mt_inq_analyse () :
BOOL mt_inq_analyse (MT_ANALYSE *分析,
MT_ANALYSE_PART 组件_ID,
double *份额);
(这些结构需在头文件 materials_table.h 中声明)。
函数 mt_calc () 可用于调用材料表。定义如下:
BOOL mt_calc (MT_ANALYSE_TYPE table_id, // 材料类型(=流体类型)(输入)
MT_FUNC_ID func_id, // 需要的函数(输入)
double para_1, // 函数的第一个参数(输入)
double para_2, // 函数的第二个参数(输入,如需要)
MT_ANALYSE *analyse, // 材料组份(MT_VRAT_OF_MRAT 时,输入
// 或者 MT_MRAT_OF_VRAT 时,输入和输出)
double *result, // 请求的函数的计算结果(输出)
MT_PHASE_ID *phase_id, // 水的相位(输出,如果有的话)
MT_FORMULATION formulation, // 要使用的水/蒸汽表配比(输入)
long *error_id); // 错误代码 (0 = 成功)
所有的参数都必须被定义。可用的数据类型和值在头文件 materials_table.h 中定义。
参数 |
数据类型 |
目的 |
有效值 |
table_id |
MT_TABLE_TYPE |
指定要使用的材料表。 |
MT_AT_WATER |
func_id |
MT_FUNC_ID |
指定要执行的函数。_OF_ 前面的字母指定结果,后面的字母指定输入参数:例如,PT 表示压力和温度,所以 H_OF_PT 表示焓是压力和温度的函数。 |
MT_H_OF_PT |
para_1 |
double |
第一个输入参数 |
对应于相应的函数: |
para_2 |
double |
第二个输入参数 |
对应于相应的函数: |
analyse |
MT_ANALYSE_TYPE |
指定材料组份(气体、液体、煤)。 mt_set_analyse 修改 或 用函数 mt_inq_analyse 读取组份。 |
份数必须以 double 值输入。材料类型必须是: |
result |
double |
这是结果值 |
对应于相应的函数: |
phase_id |
MT_PHASE_ID |
水/ 蒸汽的相位 |
MT_PI_FLUID |
formulation |
MT_FORMULATION |
水 / 蒸气表配比 |
MT_FORM_WST67 |
error_id |
long |
|
在成功的情况下为 0。 |
例如,如果要计算蒸汽的比焓,并且已知 p 和 T,可以指定:
或者要计算粗煤气的比焓,并且已知 p 和 s,可以指定:
这个例子显示了通过使用组件 65 对组件 8(见下文)进行建模。
8 号组件有三个连接:
下图显示了使用 65 号组件对上述循环的建模。这里,进口位于其下部和右侧,出口位于其上部和左侧。规格值 FPROG 被设定为2。
与之前的模型相比,现在使用了四个连接口:
下面是原始模型中泵的规格值和文件 ebsuser.c 中的相关代码。变量的名称是在线帮助中描述组件 8及其方程式使用的名称。泵的必要规格值以常数形式给定。特征曲线没有体现,这并不重要,因为在原始模型中
case 2:
//
// Case 2 (FPROG = 2):
//
// 建立一个泵的模型,以替代组件 8
//
// 方程见组件 8 的在线帮助
// 水进口连接到组件 65 的输入6。
// 压力连接到组件 65 的输入 5。
// 水出口连接到组件 65 的输出 2。
// 轴连接到组件 65 的输出 3。
//
// 规格值是:
// ETAIN = SPEC1
// ETAM = SPEC2
// M1N = SPEC3
//
// 结果值是:
// ETAI = RES1
//
// 注意,在 C 语言中,指数是从 0 开始的(即 SPEC1 = specs[0],...)
//
int rc = 0;
double etain, etai; // 标称和当前等熵效率
double etam; // 机械效率
double m1n; // 标称质量流量
double p1,h1,m1;
double p2,h2,m2;
int rcmt; // mt_calc 的返回代码
double s1,t2s,h2s,dhs,dh,t2,q2,q3;
int ii;
int phase = 0, error = 0; // 对于水 / 蒸气表
MT_FORMULATION form;
// 读取规格值
etain = data->specs[0];
etam = data->specs[1];
m1n = data->specs[2];
// 读取压力(管道 5)输入到局部变量中
p1 = data->in[5].p;
h1 = data->in[5].h;
m1 = data->in[5].m;
// 读取压力(管道 5)输入到局部变量中
p2 = data->in[4].p;
// 计算当前效率
if (data->calcparams.design == 0) {
etai = etain;
}
else {
etai = etain * (m1 / m1n);
}
// 读取水蒸气表
form = data->calcparams.wst;
// 组件 8 的方程
rcmt = mt_calc (MT_AT_WATER, MT_S_OF_PH, p1, h1, NULL, &s1 , &phase, form, &error);
assert (rcmt);
rcmt = mt_calc (MT_AT_WATER, MT_T_OF_PS, p2, s1, NULL, &t2s, &phase, form, &error);
assert (rcmt);
rcmt = mt_calc (MT_AT_WATER, MT_H_OF_PS, p2, s1, NULL, &h2s, &phase, form, &error);
assert (rcmt);
dhs = h2s - h1;
dh = dhs / etai;
h2 = h1 + dh;
rcmt = mt_calc (MT_AT_WATER, MT_T_OF_PH, p2, h2, NULL, &t2 , &phase, form, &error);
assert (rcmt);
m2 = m1;
q2 = m2 * h2;
q3 = (m2 * h2 - m1 * h1) / etam;
// 初始化所有输出值
for (ii = 0; ii < 6; ii++)
{
data->out[ii].p = 0.0;
data->out[ii].h = 0.0;
data->out[ii].m = 0.0;
}
// 设置水的输出值
data->out[1].p = p2;
data->out[1].h = h2;
data->out[1].m = m2;
// 设置轴的输出值 - p 和 m 是必要的假数
data->out[2].p = 0.01;
data->out[2].h = q3;
data->out[2].m = 1.0;
// 只计算最后一个迭代步骤的结果
if (data->calcparams.mode == 3) {
data->results[0] = etai;
// 确定设计情况下的 M1N
if (data->calcparams.design == 0) {
data->specs[2] = m1;
}
}
// 在最后一个迭代步骤中确定设计工况下的 M1N
return rc;
} break;
循环和代码生成后,可以编译和链接以创建 DLL。
点击 >> 组件 65 示例 1 << 加载示例 1(简单)。
点击 >> 组件 65 示例 2 << 加载示例 2(如上所示的泵的模拟)。
点击 >> 组件 65 示例 3 << 加载示例 3(使用分析)。