工业监控是确保生产流程稳定、安全和高效的关键环节。在化工行业中,这一点尤为重要,化工过程通常涉及高温、高压、易燃、易爆或有毒物质,任何微小的异常都可能导致安全事故或生产效率的大幅下降。随着工业4.0的到来,传统的监控手段,如人工巡检和简单的自动化系统,已经无法满足日益增长的生产规模和复杂性。化工行业开始探索更加先进的监控解决方案,以实现更深层次的数据分析、更精准的异常检测和更快速的响应机制。这些解决方案通常基于先进的信息技术,如大数据分析、机器学习、云计算和物联网技术,实现自动化和智能化的监控、预警与管理。
本文为大家介绍一个针对工业异常监控的解决方案架构,基于 DolphinDB 规则引擎,快速搭建一个化工异常检测及实时预警系统。
1. 化工系统中的实时预警模型
化工产品制备系统中,实时预警机制的建立十分关键,以迅速识别并处理生产过程中的潜在问题。系统涉及众多设备和复杂的工艺流程,需密切监控温度、压力、流速等关键参数。任何设备故障或工艺参数的异常波动都可能对生产造成影响,甚至导致生产中断或产品质量问题。因此,建立一个高效的实时预警系统对于保障生产的连续性、稳定性及产品质量至关重要。
在监控与预警的实施过程中,采用构建机理模型进行监测是一种常用的方法。机理模型,也称为物理模型或白盒模型,基于对物理、化学、生物等过程的理解,通过数学方程和物理定律描述系统行为。这种模型通常包含系统的动力学方程、质量守恒、能量守恒等,为精确监测和预警提供了科学依据。通过优化这些模型,可以进一步提高预警系统的准确性和响应速度。其特点包括:
- 准确性高:由于基于系统的物理、化学原理,机理模型能够精确描述系统的动态行为和状态变化。
- 解释性强:机理模型能够深入理解系统内部机制,帮助工程师分析和解决问题。
- 可预测性强:通过调整模型参数,机理模型可用于预测系统在不同条件下的行为。
在化工产品制备系统中,每一步流程都对应着具体的化学过程,因此非常适合构建机理模型以监测生产过程,且构建准确的机理模型对于理解系统行为、优化生产流程以及提高产品质量至关重要。
2. 工业丙烯腈制备监测场景
以工业丙烯腈的制备为例,反应系统的监控至关重要。丙烯腈的生产以丙烯、氨、空气为原料,在催化剂作用下生成丙烯腈及副产物。在此过程中,需要基于反应温度、进料比、出料比、催化剂含量等指标构建机理模型,对反应系统进行实时监测,以确保反应的正常进行。
- 反应温度的监测
从热力学角度来看,较高的反应温度有利于反应进行。然而,温度越高,丙烯的转化率虽然上升,但选择性会下降,导致大量副产物的产生,且温度过高会导致催化剂过热劣化,缩短其使用寿命。而反应温度过低,则会降低丙烯的转化率和丙烯腈的收率。
假设反应的最佳温度应保持在435~440℃,且最大径向温差不应超过2℃,此时丙烯腈的收率最高。为了保持反应器的温度,需要通过使用反应器内的U型管束进行调节。因此,在实际环境中,需要实时监测温度传感器的数据异常,以便生产监控人员及时调整温度。
- 进出料比监测
原料的进料比例无疑会直接影响到反应的结果,因而操作人员也需要控制各原料的进料比,保障反应正常。
- 空烯比
空烯比过高,会导致丙烯腈发生二次反应,降低其收率;空烯比过低,则会导致反应不完全,并使催化剂因缺氧而失去活性。由于反应环境的变化,空烯比并不是绝对固定的。因此,还需根据出料中的尾氧浓度来判断反应情况。即使空烯比正常,如果尾氧浓度超出范围,仍表明生产过程中存在异常。因此,对空烯比的判断需要结合进料比例和尾氧浓度。通常将空烯比控制在8.8-11.0之间,尾氧浓度控制在0.5~2.0%之间。
2. 氨烯比
氨烯比过高,会增加副产物,导致氨和其他原料的消耗增加;氨烯比过低,会增加丙烯醛和丙烯酸含量,在后续回收中生成聚合物,并降低丙烯转化率和丙烯腈收率。氨烯比通常应控制在1.10~1.35之间,以保证反应正常进行。当数据记录反应进料比出现异常时,此时我们就可以及时调整进料量,优化生成过程。
- 催化剂控制
催化剂的装载量可以通过重时空速(WHSV)来判断,WHSV 的定义是丙烯进料量除以催化剂装载量。WHSV 的范围通常是取决于反应器的设计符合。该案例中,WHSV 的取值范围为0.07~0.08h-1间。当出现重时空速异常时,操作人员就需要调整催化剂量或原料进量。
3. DolphinDB 工业异常监控解决方案
- 解决方案
结合 DolphinDB 规则引擎,针对上述的监控场景,我们提出了如下针对化工系统实时异常检测的解决方案架构:
该架构中,数据源由传感器数据组成,可以通过消息中间件、API、ODBC 等方式将采集的传感器数据写入 DolphinDB 流表。
- 原始表:这是存储原始数据的流表,通过订阅流表将数据实时注入规则引擎。
- 静态规则表:这是存储在 DolphinDB 中的静态信息表,包含每个测点的规则信息及对应的处理策略。
- 检测结果表:该表用于存储规则引擎的检测结果。用户可以订阅此结果表,并自定义处理逻辑,将异常结果输入下游流表。
- 异常处理表:用于接收经过规则引擎回调函数处理的异常处理结果。
结果输出方面,DolphinDB 可以通过插件主动推送检测结果,或由下游应用系统主动拉取数据。
- 规则引擎
规则引擎是 DolphinDB 为应对实时的异常检测和风控管理等场景推出的流数据引擎,支持对不同的数据集应用不同的检测规则,且检测规则可以动态增删,十分灵活。此外,规则引擎还支持指定回调函数,可以在其中对检测结果执行异常处理、过滤等操作。
引擎计算机制可以参考下图:
4. 快速搭建一个异常监控系统
本文将以一个轻量化案例展示如何使用 DolphinDB 实现上述架构中的核心部分,进而完成化工场景中的实时异常监测,主要包括规则表的解析、规则引擎的实现及异常结果的处理。
4.1 规则表解析
首先我们模拟一个静态规则表,静态规则表中存储了各设备所对应的规则信息,作为我们后续使用规则引擎进行异常检测的依据。静态规则表结构如下:
字段名称 | 字段类型 | 说明 |
---|---|---|
devId | INT | 设备ID |
ruleId | INT | 该条规则对应的规则编号 |
param | STRING | 规则检测的指标名称 |
lowLimit | DOUBLE | 测点值下界 |
highLimit | DOUBLE | 测点值上界 |
calFunc | STRING | 如 param 是计算结果值,则需要提供对应的计算公司 |
exceptionHandling | STRING | 出现异常对应的处理方案 |
根据前文中场景,我们使用如下脚本创建一个静态规则表:
//模拟规则信息
devId = stretch([1,2],7)
param = `temp1`temp2`tempDif`airPropyleneRatio`oxygenRatio
`ammoniaPropyleneRatio`WHSV
ruleId = 0..3 <- 0..2
lowLimit = [435,435,0,8.8,0.5,1.10,0.07]
highLimit= [440,440,2,11.0,2.0,1.35,0.08]
calFunc = [NULL,NULL,"abs(temp2-temp1)",NULL,NULL,NULL,
'propyleneAmount\\catalystAmount']
exceptionHandling=["点位1温度超出正常范围,调整U形管数量","点位2温度超出正常范围,调整U形管数量",
"温度分布不均,调整U形管分布","空烯比异常,调整空气、丙烯进料比","尾氧含量异常,调整空气、丙烯进料比",
"氨烯比异常,调整氨气、丙烯进料比","重时空速异常,调整催化剂用量或丙烯进料量"]
//创建配置表
configTable = table(devId,ruleId,param,lowLimit,highLimit,calFunc,exceptionHandling)
使用 DolphinDB 脚本将上述规则配置表解析为适配规则引擎的规则集:
keys = [1,2,NULL]
rules = []
for(key in keys){
if(key!=NULL){//key=1
ruleTable = select * from configTable where id=key
tmp = []
for(rule in ruleTable){
paramTmp = iif(rule.calFunc!=NULL,rule.calFunc,rule.param)
ruleTmp = parseExpr(rule.lowLimit +"<"+ paramTmp+"<"+rule.highLimit)
tmp.append!(ruleTmp)
}
rules.append!(tmp)
}
}
//添加一个默认规则条件
rules.append!([<temp1<0>])
//生成规则集
ruleSets = dict(keys,rules)
生成的规则集是一个字典,其中键为设备ID,值是对应设备的规则,每个规则表示为一个元组。在规则引擎的规则集中,必须包含一条默认规则,该规则对应键为 NULL。如果输入数据未匹配任何设备的具体规则,则会应用默认规则。
4.2 规则引擎创建
当我们获取到规则集后,即可根据规则集创建一个规则引擎:
//创建数据流表,作为规则引擎的数据源和输出表
colNames = `devId`ts`temp1`temp2`airPropyleneRatio`oxygenRatio`ammoniaPropyleneRatio`propyleneAmount`catalystAmount
colTypes = [INT,TIMESTAMP,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT]
share streamTable(10000:0,colNames,colTypes) as orignData
share streamTable(10000:0,colNames <- `rule,colTypes <- [INT]) as result
//创建规则引擎
createRuleEngine(name="rule1",ruleSets=ruleSets,dummyTable=orignData,
outputColumns=colNames,outputTable=result,policy="shortcut",ruleSetColumn="devId")
//订阅原始数据表,将数据注入规则引擎
subscribeTable(tableName="orignData",actionName="dataToRule",offset=0,
handler=append!{getStreamEngine("rule1")},msgAsTable=true,batchSize=1000,throttle=1)
上述代码中,我们首先创建了两个流表 orignData、result,orignData 接收设备传感器上传的原始数据,作为规则引擎的数据源,result 作为输出表接收规则引擎检测后的结果输出。之后创建了一个规则引擎 rule1,ruleSets 为我们前文解析的规则集。有关规则引擎的详细说明,请参考 createRuleEngine。最后我们订阅原始数据表,将数据注入规则引擎中,即完成了规则引擎创建的完整流程。
4.3 功能验证
本文仅使用两个测点的数据模拟进行功能验证,每个测点的采集频率为 10 ms,具体数据模拟脚本见附件 simulateData 函数。本文模拟生成的数据完全随机,故结果输出可能与下文不同。
查看输出结果表:
select * from result
其中前九列为我们自定义输出列,最后一列 rule 即为规则引擎的检测结果,为空则表示当前测点无异常,2则表示该测点不符合第三条规则,出现异常。
可以看到规则引擎的直接输出中,包含了异常记录和正常记录,且异常记录中的 rule,只是提供了一个异常标识。进一步我们希望能够直接获取异常信息和对应的操作方案。
4.4 检测结果处理
想要直接获取异常信息和对应的操作方案,我们需要将检测结果处理成我们需要的形式。检测结果的处理有两种方案:
- 使用规则引擎的回调函数处理异常结果。在这种方法中,规则引擎每处理一行记录时都会调用回调函数,具有较低的延迟。缺点是如果对订阅结果进行逐条处理,可能会导致规则引擎堵塞,且对回调函数的修改需要重定义整个规则引擎。因此这一方案适用于数据量较少、数据频率较低且结果处理逻辑固定的场景,即不会影响规则引擎的性能,还可提升异常响应速度。
- 订阅检测结果表,并通过自定义的处理函数(handler)进行批量处理。这种方法会对每一批次的数据调用 handler 函数进行处理,从而提高结果处理的效率。这一方案适用于数据量较大的场景,当数据量较大事,规则引擎本身负荷较高,频繁调用回调函数不利于系统的稳定性。
两种方案都需要自定义处理函数来处理异常结果,选择哪种方案取决于实际应用场景的需求。
- 清理环境
unsubscribeTable(tableName="orignData",actionName="dataToRule")
dropStreamEngine(`rule1)
dropStreamTable(`orignData)
dropStreamTable(`result)
运行上述脚本清理环境后,重新定义流表 orignData、result。
- 定义处理后的异常记录表
colNames = `devId`ts`temp1`temp2`airPropyleneRatio`oxygenRatio`ammoniaPropyleneRatio
`propyleneAmount`catalystAmount`exceptionHandling
colTypes = [INT,TIMESTAMP,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT,FLOAT,STRING]
share streamTable(10000:0,colNames,colTypes) as warningTable
- 使用回调函数进行结果处理
我们定义如下函数对数据进行处理,当测点出现异常时,则通过静态规则表获取异常处理方式,并将记录输出到异常记录表中:
def exceptionHandling(result,warningTableName,configTable){
if(result.rule != NULL){
tmp = select devId,ts,temp1,temp2,airPropyleneRatio,oxygenRatio,
ammoniaPropyleneRatio,propyleneAmount,catalystAmount, exceptionHandling
from result
left join configTable on result.devId = configTable.devId
and result.rule=configTable.ruleId
objByName(warningTableName).append!(tmp)
}
}
我们在规则引擎指定 callback 参数为 exceptionHandling
,则经过规则引擎检测后的结果会自动调用 exceptionHandling
函数进行处理:
//重新定义规则引擎增加回调函数
createRuleEngine(name="rule1",ruleSets=ruleSets,dummyTable=orignData,
outputColumns=colNames,outputTable=result,policy="shortcut",ruleSetColumn="devId",
callback=exceptionHandling{,"warningTable",configTable})
//新建订阅
subscribeTable(tableName="orignData",actionName="dataToRule",offset=0,
handler=append!{getStreamEngine("rule1")},msgAsTable=true,batchSize=1000,throttle=1)
- 订阅检测结果表
定义 handler 函数,并订阅检测结果表。handler 函数中进行的处理与回调函数中进行的处理基本一致。
//定义 handler 函数 resultWarning,进行结果处理
def resultWarning(msg,warningTableName,configTable){
tmp = select devId,ts,temp1,temp2,airPropyleneRatio,oxygenRatio,
ammoniaPropyleneRatio,propyleneAmount,catalystAmount, exceptionHandling
from msg
left join configTable on msg.devId = configTable.devId
and msg.rule=configTable.ruleId
tmp = select * from tmp where exceptionHandling!=NULL
objByName(warningTableName).append!(tmp)
}
//订阅检测结果表
subscribeTable(tableName="result",actionName="resultWarning",offset=0,
handler=resultWarning{,"warningTable",configTable},msgAsTable=true,batchSize=1000,
throttle=1)
- 扩展功能验证
运行数据模拟脚本,查看 warningTable 表中异常记录:
rule 已被处理为静态规则表中的异常处理策略,且两种方案的处理结果完全一致。
5. 小结
本教程通过一个具体的异常监控实例,基于 DolphinDB 的规则引擎,详细阐述了如何迅速构建一个全面的异常监控系统。通过这一案例,用户将深入了解到使用 DolphinDB 构建异常监控系统的独特优势,并获得快速实现高效监控系统的解决方案。此外,教程中所展示的监控案例不仅具有参考价值,还可以灵活应用于其他相似场景,进一步拓展其应用范围。