1. 为什么把PTC-6-2004试验计算搬进Pycharm
1.1 老办法的痛点
做汽轮机性能考核试验的人,基本都经历过那段被Excel支配的日子。测点数据先从DCS导出,再手工填进一个又一个sheet,热量平衡反复试算,修正曲线的插值靠VLOOKUP,中间改一个参数整张表跟着乱。厂家给的黑盒程序又只出结果不给过程,输入参数稍微超出适用范围,结果直接飞掉,你连错在哪儿都查不到。
我这次接手的CC350-16.7/0.98/0.5/538/538机组,是典型的亚临界一次再热抽凝式供热机组,额定功率350MW,主蒸汽16.7MPa/538°C,再热蒸汽温度538°C,带0.98MPa和0.5MPa两级可调抽汽。这种机组做一次完整的性能试验,测点数量在两百个上下,稳态工况至少完整采集六组,每组数据还要按PTC-6-2004的要求做稳定性判定,有效数据段取平均值。手工处理下来,一个工况算清楚至少一整天,而且非常容易在某个中间环节出错,复核还得从头再来一遍。
1.2 计算链路拆开看:试验计算、一类修正、二类修正
PTC-6-2004,也就是ASME汽轮机性能试验规程,它的核心逻辑其实不复杂:先把试验实测数据整理成汽轮机热耗率和出力,再把试验工况下得到的结果修正到合同保证工况,看机组是不是达到了保证值。真正有门槛的是"修正"这一层。
工程上修正分两类。一类修正处理的是主蒸汽压力、主蒸汽温度、再热蒸汽温度、再热蒸汽压损这些改变整个热力循环状态的参数偏差,这类修正必须通过整机循环重新计算才能得到,不能靠单点查曲线糊弄。二类修正处理的是排汽压力、供热抽汽参数、功率因数这些相对独立、但同样影响最终结果的边界条件。两类修正不能揉在一起算,因为修正顺序不同,最终结果会有百分之零点几的差别,而考核试验通常较真到小数点后一位,这个差别不能忽视。
所以我把整个工程拆成了三个核心模块,对应三件事:试验计算、一类修正、二类修正。全程在Pycharm里开发调试,整套工程连同注释、说明文档写下来接近五万七千字。下面把每个模块的设计思路、关键算法和踩过的坑拆开讲。
2. 先读懂型号参数,再定计算边界
2.1 CC350-16.7/0.98/0.5/538/538的工程含义
写代码之前,先要把这台机组的型号参数吃透。按国内抽凝式供热机组型号的通用标注习惯,这台机器的主要设计参数如下:
| 参数 | 数值 | 含义 |
|---|---|---|
| 额定功率 | 350 MW | 发电机端额定输出 |
| 主蒸汽压力 | 16.7 MPa(a) | 高压主汽阀前 |
| 一级抽汽压力 | 0.98 MPa(a) | 工业抽汽,可调 |
| 二级抽汽压力 | 0.5 MPa(a) | 低压采暖抽汽,可调 |
| 主蒸汽温度 | 538 °C | 主汽阀前 |
| 再热蒸汽温度 | 538 °C | 中压联合汽阀前 |
两级可调抽汽的存在,意味着这台机组不能按纯凝工况的模型去算。抽汽既承担对外供热功能,又参与回热系统,抽汽流量和参数的偏差会直接影响低压缸的做功份额。在一类修正和二类修正的边界划分上,两级抽汽的修正方式完全不同,这个后面细说。
2.2 计算边界:把锅炉隔离在循环之外
PTC-6整机性能计算的经典做法,是把锅炉当成一个黑箱——汽轮机侧的能量输入是主蒸汽和再热蒸汽,能量输出是冷再热蒸汽、最终给水和对外抽汽,再加上发电机功率。汽轮机热耗率就是进入这个边界的热量除以发出的电量:
# 流量单位 kg/h,焓单位 kJ/kg,功率单位 kW Q_in = (w_ms * h_ms + w_hrh * h_hrh # 进入中压缸的热再热蒸汽 - w_crh * h_crh # 高压缸排汽返回锅炉的冷再热蒸汽 - w_fw * h_fw # 最终给水离开汽轮机循环 - w_ext * h_ext) # 对外供热抽汽离开循环 hr = Q_in / P_gen # 单位 kJ/kWh这里最容易漏掉的是冷再热和最终给水两项的符号。不少人第一次写公式只算了主蒸汽和热再热,结果热耗率偏大百分之三十以上,整个报告直接报废。把锅炉边界画清楚,能量流进流出理清楚,后面的修正才有讨论基础。
2.3 计算模块的输入输出关系
三个模块的数据流是单向串联的:试验计算模块吃原始测点数据,输出实测热耗率和缸效率;一类修正模块吃试验计算的输出,加上设计保证参数,输出修正到一类工况的热耗率;二类修正模块再叠加排汽压力等边界修正,输出最终考核热耗率。模块之间用标准数据类传递,中间量全部落盘到CSV,方便出问题回溯。
我的工程里,这三个模块分别对应test_calc.py、corr_type1.py、corr_type2.py三个主文件,公共的物性计算、数据规整、结果输出放在common目录下。
3. 试验计算模块:从原始测点到热耗率
3.1 测点清单与数据规整
试验计算的第一步不是算,而是把两百多个测点整理成结构化数据。我按PTC-6-2004对测点布置的要求,把测点分成五组:主蒸汽与再热蒸汽参数、各级抽汽参数、回热系统参数、凝汽器与排汽参数、发电机电气参数。
import pandas as pd def load_test_case(excel_path, sheet_name): df = pd.read_excel(excel_path, sheet_name=sheet_name, header=0) df = df.set_index("测点编号") return df每个工况采集完成后,先做稳态筛选。规程要求试验段内主要参数波动不超过规定范围,比如主蒸汽温度偏差控制在±4°C以内。我的做法是在Pycharm里写一个滑动窗口判定函数,对每个关键测点的时间序列做滚动均值和滚动标准差判断,自动截取满足稳定条件的时间窗口作为有效数据段。这一步看着不起眼,实际上直接决定后面所有计算结果的可信度。
3.2 热量平衡法与热耗率计算
数据规整好之后,先计算各测点焓值。压力温度已知,焓值直接用IAPWS-IF97物性库计算,这段代码是整个工程所有模块共同的地基:
from iapws import IAPWS97 def h_pt(p_mpa, t_c): """已知压力(MPa)和温度(°C),返回比焓(kJ/kg)""" st = IAPWS97(P=p_mpa, T=t_c + 273.15) return st.h def h_ps(p_mpa, s_kj_kgk): """已知压力和熵,迭代求比焓,用于等熵过程计算""" h_lo, h_hi = 100.0, 4500.0 for _ in range(80): h_mid = 0.5 * (h_lo + h_hi) st = IAPWS97(P=p_mpa, h=h_mid) if st.s < s_kj_kgk / 1000.0: # 注意iapws熵单位是kJ/(kg·K) h_lo = h_mid else: h_hi = h_mid return 0.5 * (h_lo + h_hi)焓值算完,按2.2小节的公式计算Q_in和热耗率。同时按高压缸、中压缸、低压缸分段计算缸效率,这个缸效率在后面一类修正里要当作不变量来用,所以必须在这个模块里就算准。缸效率的定义是实际焓降除以等熵焓降,具体到高压缸就是主蒸汽焓减去高压缸排汽焓,除以主蒸汽焓减去等熵排汽焓。
3.3 流量不平衡的处理
实测流量几乎不可能天然闭合——主蒸汽流量、抽汽流量、排气流量之间总有几个百分点的出入。PTC-6-2004里的标准做法是优先采用高精度的喉部取压流量喷嘴测量主蒸汽流量,其他流量通过热平衡反推。现场条件不具备时,工程上常用"给水流量+炉侧修正"或者"凝结水流量+加热器反推"来校核主蒸汽流量。
我在代码里做了两个层面的处理。第一层是质量平衡校核:用各段抽汽流量加排汽流量去对比主蒸汽流量,误差超过1%就直接把该工况标记为可疑工况,提醒人工检查。第二层是能量平衡校核:把计算得到的热耗率与电功率、排汽焓交叉验证,排汽焓如果落在湿蒸汽区的不合理位置,说明前面的焓值计算有误,需要重新检查测量点。这两层校验通过后,才允许进入修正环节。
4. 一类修正:把试验工况拉回到保证工况
4.1 一类修正要解决的问题
试验不可能正好在保证参数下做,主蒸汽压力差个0.2MPa、温度差个5°C都是常有的事。一类修正是把整个循环重新计算一遍,得到"如果机组在保证参数下运行,热耗率应该是多少"。它和单纯乘一个修正系数的本质区别在于:改一个参数,所有抽汽压力、抽汽流量、回热抽汽量、再热流量都会跟着变,必须做整机热平衡重构。
4.2 分段模型与弗留格尔公式
我采用的模型是"缸效率不变+弗留格尔流量修正"。先假设在试验到保证工况的偏差范围内,高压缸、中压缸、低压缸的效率保持不变,这是PTC-6认可的近似方法,误差在工程可接受范围内。然后,当初压改变时,汽轮机各级组的流量和压力关系用弗留格尔公式描述:
import math def flugel_flow(w0, p1, p2, t1, p1_0, p2_0, t1_0): """ 弗留格尔公式:由基准工况流量推算新工况流量 w0 : 基准工况流量 p1,p2: 新工况级组前、后压力 t1 : 新工况级组前温度 """ ratio = (p1 ** 2 - p2 ** 2) / (p1_0 ** 2 - p2_0 ** 2) temp_ratio = (t1_0 + 273.15) / (t1 + 273.15) return w0 * math.sqrt(ratio * temp_ratio)实际使用时,弗留格尔公式的精度取决于级组前后压力的取值。对高压缸,级组前是主蒸汽压力,级组后是冷再热压力;对中压缸和低压缸,级组前分别对应热再热压力和低压缸进口压力,级组后为排汽压力。压力取值点一定不要搞混,工程上有个常见的低级错误,就是把热再热压力当成中压缸前压力,实际上中压联合汽阀后和中压第一级前还有相当一部分节流损失。
4.3 温度修正的焓值重算
主蒸汽温度和再热蒸汽温度修正,不能简单地把温度偏差对应的焓差加进去,而是必须重新计算膨胀线。具体实现是这样的:主蒸汽温度改成保证值后,高压缸入口焓按新温度计算,高压缸等熵焓降按4.2的缸效率折算实际焓降,得到冷再热新焓值;冷再热焓加上再热器吸热量得到热再热焓;中压缸、低压缸依次往下推。其中等熵过程的终点焓要用3.2小节的h_ps函数迭代求解,这是个高频调用,性能上要写成向量化或者加缓存,否则整个修正循环会跑到怀疑人生。
4.4 修正顺序与收敛迭代
一类修正内部必须迭代。原因很简单:主蒸汽压力变了,各级组流量分布变,抽汽压力变,抽汽流量的变化又反过来改变再热蒸汽流量,再热压损跟着变,这一圈走完,高压缸的排汽压力和主蒸汽流量又要微调。
我的收敛逻辑是:
- 先用试验工况的流量和压力作为初值。
- 修正主蒸汽压力到保证值,用弗留格尔公式重新分布各级组流量。
- 按新流量分布计算各级抽汽压力,调用回热加热器模型重新计算给水焓升分配。
- 修正主蒸汽温度、再热蒸汽温度,重算各级焓值。
- 计算新的再热蒸汽流量和冷再热压力,回到第2步。
- 直到前后两轮热耗率变化小于0.001kJ/kWh,或者迭代次数超过50次。
实际跑下来,绝大多数工况在十轮以内收敛,少数供热抽汽量大的工况会波动,需要给迭代加阻尼因子,让每次调整只走30%到50%的步长,避免在两三个值之间来回震荡。
5. 二类修正:排汽压力与外部系统边界
5.1 为什么二类修正不能并入一类
一类修正是靠热力循环重新计算来完成的,它要求整个循环是封闭的、可计算的。但排汽压力的修正没法纳入这个框架,原因在于排汽压力对低压缸效率和末级排汽损失的影响高度非线性,而且在低背压工况下还牵扯到末级叶片的气动状态剧烈变化,单纯用等熵模型强行算,误差会非常大。所以工程惯例是把它放到二类修正里,用专门的修正曲线来做。
5.2 排汽压力修正曲线的拟合和应用
制造厂一般会在性能保证书中给出排汽压力对热耗率、出力的修正曲线,有的给离散表格,有的给曲线图。我的代码里专门写了一个曲线拟合器:把厂家表格里的离散点读进来,用分段三次多项式拟合,修正量按热耗率变化百分比输出。
import numpy as np def fit_exhaust_pressure_curve(pressure_points, hr_delta_points): # 每两个相邻点之间做三次多项式插值,保证曲线处处连续 return { "x": pressure_points, "y": hr_delta_points, "splines": [ np.polyfit( [pressure_points[i - 1], pressure_points[i], pressure_points[i]], # 局部拟合点 [hr_delta_points[i - 1], hr_delta_points[i], hr_delta_points[i]], 2) for i in range(1, len(pressure_points)) ] }这里有个特别需要注意的坑:厂家曲线往往是在某个特定循环水流量、特定清洁系数下测得的,现场试验时如果循环水温度偏离设计太多,直接套用厂家曲线会引入一条系统性偏差。稳妥的做法是,在试验期间同步做排汽压力扰动工况,用实测数据对厂家曲线做校核,偏差超过0.1%就把曲线平移或用最小二乘重新标定一次。
5.3 供热抽汽参数修正与修正量的叠加顺序
这台机组有0.98MPa工业抽汽和0.5MPa采暖抽汽,试验期间抽汽压力和抽汽流量与保证工况不一致时,也需要修正。抽汽流量偏差对热耗率的影响其实已经在试验计算模块里通过热平衡体现了一部分,但PTC-6的规范做法是:把抽汽流量修正单独列在二类修正中,确保考核结论和制造厂的修正算法口径一致。抽汽温度、压力的修正则按一类修正的循环重算法处理,因为抽汽压力改变会牵动回热系统参数。
修正量的最终叠加,我用的是连乘法,每个修正项计算为修正系数(1加上相对变化率),热耗率从试验值开始,按固定顺序依次乘过去:
hr_final = hr_test for factor in [corr_type1, corr_exhaust, corr_extract_flow]: hr_final *= factor顺序固定的原因是某些修正项之间弱相关,先乘后乘理论上没区别,但在数值上会有细微差异,考核验收时最忌讳口径不一致。我把顺序写死在配置里,报告中自动标注"修正顺序:一类修正→排汽压力→抽汽流量",保证任何人对结果复核都能复现。
6. 编码现场的真实坑位
6.1 物性库的单位和临界区插值陷阱
iapws库用起来方便,但单位问题让我栽过一次。它的P参数单位是MPa,T是K,而很多试验数据源给的是kPa和°C,换算少写一个系数,焓值就完全不对。我在公共模块里写死了单位归一化,所有外部输入一律先转成MPa、°C再进物性函数。另外湿蒸汽区里的等熵过程计算,直接用IAPWS97(P=..., h=...)时可能落到两相区,返回的x表示干度,这时候一定要检查干度是否在合理范围内,否则后面的缸效率计算会得出负焓降这种离谱结果。
6.2 迭代发散与初值选择
一类修正的嵌套迭代,最大的敌人是振荡。我最早用全步长更新,主蒸汽压力修正到保证值后,抽汽流量变化过大,再热流量跟着过冲,热耗率在两个值之间来回跳。后来改成阻尼更新,只把计算值和当前值的差的40%叠加进去,迭代立刻稳定了。初值方面,直接用试验工况的流量和压力作为基准是安全的,千万不要用设计工况的流量启动迭代,否则在供热抽汽大偏差工况下,弗留格尔公式很容易把流量算到不合理区间。
6.3 与厂家热平衡报告的比对校验
代码写完不等于算得对。我拿这台机组的历史验收试验报告做回归验证,用报告里的原始测点数据重算,考核热耗率与报告结论的偏差控制在0.05%以内才算通过校验。具体比对时先比对试验计算模块的中间量,再逐项比对各修正量,哪一项对不上就单独排查哪一项。这种做法强烈建议做完,它能把隐藏在代码深处的问题在发布前暴露出来,比事后在现场翻车强一百倍。
6.4 结果输出的可追溯性
计算报告必须能追溯到任何一个中间数值。我的做法是把每个工况、每一轮迭代的中间量全部追加写入一个CSV日志文件,包括各缸效率、各级组流量、各修正系数、迭代误差。这样出了问题可以直接定位到是哪一轮迭代、哪个参数引起的异常,不用从头到尾盲查。说实话,这五万七千字里有相当一大半是被这种日志设计和注释说明撑起来的,但回头看,每一行注释在后来改版调试时都省了大功夫。
7. 这套代码的工程边界与复用建议
7.1 适用机型边界
代码里的核心逻辑不绑定具体机型,抽汽级数、回热级数、加热器台数都做成了配置文件,换一台同级别的再热机组,只需要改配置重新标定。但有两块东西依赖厂家数据,换机型必须重新获取:一是低压缸末级排汽损失修正曲线,二是排汽压力对热耗率的修正曲线。这两块是不可压缩的黑盒输入,再强的循环重算模型也替代不了。
7.2 给准备自研试验计算程序的同行几点建议
第一,先做数据一致性检查再做计算,宁可多花十分钟验证测点有效性,也不要省这个环节直接算,否则一个坏点就能毁掉整个工况。第二,所有中间量都落盘,日志越详细越好,调试时你会感谢当时的自己。第三,版本管理一定要用,我在Pycharm里配合Git,每次修改算法都打标签,出问题能随时回退。第四,认真读一遍PTC-6-2004原文,特别是关于修正顺序、流量测量、稳态判定的章节,很多工程争议翻原版规范就能找到答案。
这套代码从搭框架到校验通过,前后折腾了几个月的业余时间,过程确实不易,尤其是各种边界工况反复调参数的日子。好在最后换来了一个能直接复用、结果经得起复核的工具。有正在被同类试验计算困扰的同行,欢迎多交流,希望这篇过程记录能让你少走几步弯路。