前言

别的不说了,纯粹是因为热爱,偶然间知道了CAPE-OPEN标准,同时喜欢化工和编程,自然就沉迷化工流程模拟开发了,在这里记录一下自己的学习过程。

CAPE-OPEN是基于COM组件来的,在C++中ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板库,可以建立COM组件,然后通过ASP页面中的脚本对COM对象进行调用。这种COM组件可以包含属性页、对话框等控件。

热力学物性包是什么

上图是Aspen、HYSYS、PROII等流程模拟软件的简单计算过程图,接下来逐步分解它的一个计算过程和构成。

首先一个最简单的工艺流程应该包含三个元素:一个进口物流,一个单元模块,一个出口物流,我们称进出口物料这个对象为界面流股,单元模块就是单元模块,包括混合器、换热器、塔器、泵等。

整个计算过程主要有下面三个步骤:

  • 进口流股闪蒸:主要参数有组成、温度、压力
  • 单元模块根据进料计算,计算完毕之后设置出口流股
  • 出口流股闪蒸:主要参数有组成、温度、压力

在每一步计算的过程中,是离不开状态方程的,也就是我们说的热力学部分,实际上我们在模拟的时候输入的参数,比如组分、温度、压力这些并不是直接就赋予到状态方程中去计算了,单元模块也不是直接会调用热力学部分进行计算,而是引入了一个中间层:物流对象。

为什么需要中间层呢?在实际计算过程中,整个流程可能根据分区/工段的不同,而采用的物性方法不同,所以需要不同的物流对象来访问不同的热力学部分(物性集)。

每个流股或单元模块都会产生一个物流对象,这个物流对象中存储着对应的物性集。

界面流股也会储存一部分参数,比如组成、温度、压力,但实际上大部分参数例如密度、焓等都会储存在物流对象中,这并不冲突。

上图是在我们新建一个模拟文件时,物性包是如何被访问和调用的。

在创建一个流程或者工段的时候,软件首先会访问物性包管理者(PropertyPackageManager),物性包管理者有一个物性包(FluidPackage/PropertyPackage)的列表,比如NRTL、SRK、UNIFAC等;

我们选择了一个需要的物性包之后,软件会将这个物性包加载到物流对象模板中,从而产生出指定了物性包的物流对象;

这个时候我们的流程就可以去调用一个个物流对象进行计算,需要注意的是,该过程在一个流程/工段的模拟过程中只会进行一次,也就是创建流程的时候才会进行一次(添加组分,更改物性包都算新建流程的概念,因为会更新物流对象)。

在正常的模拟计算过程中,计算流程是如下图这样的:

工艺流程和物流对象首先进行交互,向物流对象发送初始参数,例如流量、组分、温度、压力等,这个时候物流对象就有了属性,有哪些组分、具有哪个状态方程、允许的相态是什么,物流对象是不具有计算功能的,只是一个参数的存储和中转站;

物流对象紧接着将所有参数交给热力学部分,通过热力学部分中的相平衡/闪蒸模块、焓计算、密度计算等等,去按照要求计算所需要的值,计算完毕之后再返回给物流对象,物流对象存储之后再反馈给界面流股,也就是工艺流程中的计算结果。

在整个过程中热力学部分是固定的,在创建过程中是一次性创建好的,但是物流对象是随着工艺流程/工段中流股或单元模块的改变而改变的。

现在来回答标题的问题,热力学物性包是什么?它是一个含有一个流程/工段中所有组分,以及所设定的状态方程,固定的,不随流程而改变的数据集。

物性包的导出及使用

以Aspen V11和COFE V3.7为例

需要提前说明的是Aspen对CAPE-OPEN的物性包支持度或者说是兼容度是很差的,甚至在高版本的软件中已经取消了物性包的导入功能(我反正是没找到)

虽然说Aspen目前(V11版本)来看是支持导出的,但是其物性包在其他软件中并不好用,本文只是做一个示例,其他严格执行CAPE-OPEN标准的软件如COFE、DWSIM等还是很好的

如果是针对Aspen来进行物性包开发的话,Aspen官方提供了一套叫做User Model的接口,可以通过软件的帮助文件学习一下,但是如果是针对跨平台开发,或者定制开发,建议还是使用CAPE-OPEN标准

虽然但是,Aspen对CAPE开发的单元模块是支持或兼容度很高的,在这里可以引用其他软件开发的单元模块:

那么物性包的导入导出有什么意义呢?比如我们使用Aspen导出一个含有组分、状态方程的一个物性包,使用COFE软件导入那么意味着在COFE软件中构建的流程里,我们使用的单元模块是COFE软件的,但是计算过程中的热力学方法使用的是我们Aspen中的;

或者在不同的软件里使用同一个CAPE开发的单元模块,这样可以达到对某些流程的高度自定义,可以更接近真实流程,可以输入更多的修正值,让模拟计算结果更加准确。

Aspen的物性包导出:

注:在第一个分节热力学物性包是什么里我们已经讲了,所以导出物性包时请务必已经选择好了组分和状态方程

可以看到,Aspen导出的物性包其实就是一个 *.cota 文件,同时会默认放在这个路径里,这是约定俗成的,其他的软件读取的时候也会直接在该路径下去找该文件

对于COFE,导入我们刚才导出的物性包如下:

这样就可以在COFE里使用Aspen的状态方程和组分物性数据了

但是实际上会出问题的,因为我们已经说了,Aspen对CAPE的兼容是很差的,推荐使用其他软件来使用,本文这里仅作示例

物性包的开发

前文我们已经了解过了,物性包实际上就是ATL项目,也就是动态链接库,推荐使用VisualStudio来开发,当然用其他的IDE也行,不过配置环境是非常麻烦的

打开VS2022,选择创建新项目:

名字自定义,点击创建:

直接点确定,这样就创建好了一个ATL项目,可以看到部分源文件和头文件已经自动添加进来了:

创建好项目之后就要开始添加接口了,那么添加什么接口,怎么添加,这些CAPE标准里都有相对应的文档,可以通过这个链接去下载到CAPE-OPEN的所有文档:

CAPE-OPEN官网

解压之后可以得到所有的标准文档,本文是热力学物性包开发,对应的文档名称为:

1
CO_Thermo_1.1_Specification_311.pdf

打开文档,可以看到标准的调用时序图:

可以看到 :PME 为最高也就是初始一级,全称为Process Model Environment,意为流程建模环境,也就是我们的工艺流程部分,次级就是S1:Stream,也就是我们上文中的界面流股,再接下来到 :PMEPropertySystem 也就是中间层:物流对象,物流对象再去调用更深层次的计算。在整个过程中要实现热力学部分所用到的接口如下图所示:

可以看到第一个接口就是 ICapeThermoPropertyPackageManager ,这就是上文所说的物性管理者,他包含了两个接口,一个是获取物性包列表,一个是选择物性包,那么,我们第一个接口自然就是物性包管理者了。

接下来我们添加第一个接口:

名字自定义,点击添加:

这里默认即可,直接点击完成

这样我们就添加了一个简单的接口,这里的报错不用管,是因为我们定义了接口,但没有使用,接下来直接编译一下,看看源文件是否齐全:

可以看到报了一个错误:error MSB8011: 未能注册输出。请尝试启用“逐用户重定向”

不要慌,我们需要手动开启逐用户重定向:

然后再重新生成一下:

可以看到已经编译通过了,1已跳过不用担心,是因为我们创建接口但没有调用导致的

接下来就可以直接去写调用接口的部分了,但是我们自己手写是非常麻烦且繁琐的,CAPE-OPEN直接给了一个现成的模板,可以直接去使用,通过下列链接去下载示例:

CAPE-OPEN示例:

下载好直接直接对exe文件进行解压,解压后可以看到文件夹中有一个 *.tlb 文件,对于COM组件开发来讲,tlb文件就是规定了的接口,直接将该tlb文件复制到我们的项目根目录下:

接下来我们就可以直接导入我们需要的接口:

在类视图中找到我们刚才添加的 CFluidPackageManager ,点击添加实现接口:

位置选择文件,选择刚才复制过来的标准文件,打开:

左侧就是CAPE-OPEN的所有接口,找到我们所需要的 ICapeThermoPropertyPackageManager ,点击导入

可以看到已经导入进来了,重新编译一下:

正常编译通过,可以看到导入了下面两个类:

到这里的话,流程模拟软件已经可以访问我们写的这个所谓的物性包了,尽管我们这个物性包里什么都没有,但是软件要真正的访问到我们写的这个物性包,还需要有一个敲门砖,也就是我们得告诉模拟软件,你可以访问我。

那么如何告诉模拟软件你可以访问我这个物性包呢,CAPE进行了规定,可以在自己的模块中写入固定的UUID,写入这个ID之后,其他软件就可以通过注册表来找到这个物性包,我们不需要去理解为什么是这个ID,这是CAPE-OPEN规定好的,例如:

在项目目录资源文件中可以看到,有我们创建的 *.rgs 文件,这就是注册表文件:

那么这个文件中的内容怎么写,CAPE-OPEN也提供了标注的模板,可以在我们刚才下载的示例里找到:

首先这部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'Implemented Categories'
{
{678C09A1-7D66-11D2-A67D-00105A42887F}
{CF51E383-0110-4ed8-ACB7-B50CFDE6908E}
}
CapeDescription
{
val Name = s 'CPP Ideal Property Package Manager'
val Description = s 'CO-LaN Example Ideal Thermo Property Package Manager CPP implementation'
val CapeVersion = s '1.1'
val ComponentVersion = s '1.0.0.0'
val VendorURL = s 'http://www.colan.org/'
val About = s 'CPP Ideal Property Package Manager - Copyright 2011 CO-LaN'
}

写入的位置如下:

'Implemented Categories' 部分就是我们该模块的ID,是固定的,不能修改的

CapeDescription 部分的内容是可以自己定义的,这部分是对模块的描述部分

更改完之后重新编译,需要注意的是,这里编译之后就会将我们解决方案生成的dll文件直接注册到注册表里,以方便流程模拟软件去调用。

物性包的调用

经过上述的注册之后,现在我们这个一穷二白的物性包已经可以被其他软件访问到了,比如使用COFE来尝试调用一下:

可以看到,COFE已经成功找到了我们的物性包,并且描述也展示到了,看到 Written By laugh 成就感满满的!

同样DWSIM也可以调用到我们的物性包!:

PROII也可以调用到,这里就不多赘述了

虽然说我们的物性包里现在啥都没有,但这已经是一个非常好的开头了,接下来我们就学习如何给我们一穷二白的物性包里添加东西。