:收官——FRI/KG-TOWER 二次开发水力学核算工具包(完整项目))
FRI 与 KG-TOWER 二次开发教程20收官——FRI/KG-TOWER 二次开发水力学核算工具包完整项目版本与事实声明项目名fri_kt版本0.1.0环境Python 3.8numpy 2.2.6、matplotlib 3.10.8本机实测版本。全部核算基于公开关联式复现E1/E2/E5/E7/E8/E9/E11 Ergun。本工具包不调用 FRI 或 KG-TOWER 的任何 API两者均无公开 API软件侧权威结果按第 08/14 篇的官方通道获取PRO/II 工具 报表导出、Aspen Column Analysis。FRI 的 DRP、关联式与两本 Handbook 属会员权益sources只登记公开文献编号工具包内置白名单校验。KG-TOWER 许可红线不修改/不派生/不逆向、不向 Koch-Glitsch 竞争对手分发输出由内置合规层守护。文中全部数值为示例性建模不代表任何标准规定不对应任何真实装置数据。一句话结论fri_kt0.1.0 把二十篇的纪律收敛成五个可组合的层——核心层Internals/Case/rate_tray/rate_packing/margins、批量层内容寻址case_id 断点续扫实测首轮 102 工况全算、续扫新算0、报表层宽表 操作窗口图、不确定度层CV0.1562目标风险 5% → 设计点67.6%、合规层版本成对 来源白名单 输出用途并用8 项断言的回归测试8/8 通过把 Fp 口径、泛点压降、Ergun 压降、板压降、最紧项、CV 等关键数值钉死。〇、本篇要解决的认知问题Q1一个可发布的水力学核算工具包必须包含哪五个层边界如何划分Q2为什么回归测试是这类工具包的最后一根钉子它应该钉住哪些数值Q3CLI 应该暴露哪些命令才能覆盖从单点到平台的全部使用场景Q4交付清单应该包含什么才能让第三方在没有作者在场时重跑Q5回顾整条系列哪些是铁律、哪些是最佳实践、哪些是经验法则一、机制解析1.1 五层结构与文件布局为什么这对你重要工具包的价值不在代码量而在**“每一层都能被单独替换、单独测试”**。fri_kt/ ├── __init__.py # 版本与公共 API 导出0.1.0 ├── core.py # ① 核心层数据模型 核算 裕度纯函数 ├── sweep.py # ② 批量层case_id 断点续扫 CSV 长表 ├── report.py # ③ 报表层宽表交付 三段元数据 操作窗口图 ├── uncertainty.py # ④ 不确定度层蒙特卡洛 解析反解 ├── compliance.py # ⑤ 合规层清单校验 版本成对 来源白名单 关键词扫描 └── cli.py # 命令行入口rate / sweep / report / uncertainty / compliance tests/ └── test_regression.py # 8 项断言可直接运行无需 pytest层只做绝不做的核心层给定几何与工况算水力学、算裕度读文件、写文件、读阈值配置、联网批量层生成/过滤/落盘工况修改核算逻辑、引用阈值以外的判据报表层汇总、出图、写元数据重算、改阈值不确定度层误差传播、反解设计点修改确定性核算合规层校验清单与来源、扫关键词触碰软件本体、解析其文件这条边界的意义核心层是纯函数因此可缓存、可并行、可回归第 19 篇——一旦核心层混入 I/O这三件事全部失效。1.2 回归测试钉住什么、为什么为什么这对你重要本系列从头到尾都在强调单位/口径是最大杀手。而口径错误最危险的形式是**“改动某处后所有结果都平移了一点”**——它不会被任何功能测试发现只会让历史结论与新结论不可比。回归测试就是防这个的。test_regression.py的 8 项断言实测 8/8 通过测试钉住的数值防的是什么test_fp_unit_and_flood_dpfp_m_to_ft(79)259.19dp_flood(85 ft⁻¹)2.690 inH₂O/ftFp 口径被改test_flvFLG(12,6,780,2.5)0.11324质量/摩尔比被混用test_ergun_and_flood_velocity干 697.9 Pa/m、湿 818.0 Pa/m、泛点率 61.0%Ergun 常量或持液量处理被改test_oconnell_unitsEo(2.5,0.30)41.7%、Eo(2.5,3e-4)22.1%黏度单位mPa·s↔Pa·s被改test_tray_case塔板泛点率 77.0%、板压降 255.1 mm塔板压降四项分解被改test_margins_bindingbinding dP、okFalse裕度归一化或阈值被改test_uncertaintyCV0.1562、设计点 67.6%误差合成规则被改test_compliance良好清单零问题、坏清单 ≥4 条合规校验被削弱关键点这些断言全部是数值不是函数能跑通。能跑通的测试挡不住口径漂移。1.3 CLI 覆盖面五条命令覆盖四种使用形态命令使用形态典型调用rate 内件单点核算工程师手算替代python -m fri_kt.cli rate IMTP#40sweep批量扫描可断点续扫python -m fri_kt.cli sweep --out _kt_sweep.csvreport报表交付宽表 图python -m fri_kt.cli reportuncertainty裕度反解风险→设计点python -m fri_kt.cli uncertaintycompliance合规闸门CI/计划任务python -m fri_kt.cli compliance --manifest m.json设计要点rate的退出码是判据合格 0 / 越限 2这样它可以直接被流水线用作门禁——工具包的入口应当是可被判定的而不是只打印的。1.4 交付清单第三方要能重跑需要拿到五件东西代码fri_kt包含版本号 0.1.0依赖清单Python 版本 numpy/matplotlib 版本本系列用到的是 numpy 2.2.6、matplotlib 3.10.8来源清单sourcesE1/E2/E5/E7/E8/E9/E11 Ergun均公开文献单位集units内部 SI压降 Pa/m 与 mm 液柱并列展示Fp 存储用 ft⁻¹阈值版本limits含版本号与调整历史。经验法则交付物的最小充分集就是这五件少一件重跑就有歧义。1.5 知识图谱回顾二十篇怎么串起来的入门01-04 ── 边界与地基 01 全景与二分法官方通道 vs 公开关联式复现 02 环境盘点KG-TOWER 5.4.x 安装与许可红线FRI 资源公开关联式弹药库 E1..E13 03 第一个算例E1/E2 ErgunFp 双口径陷阱 2.18× 04 数据模型四层对象内部统一 SIcase_id 核心05-08 ── 物理与软件面 05 塔板机制三类泛点、压降四项、降液管、漏液、OConnell 06 填料机制载点/泛点、GPDC、Fp~a/ε³、持液量、HTU-NTU/HETP 07 第一个实战KLM 九步塔径反算操作窗口 65%~110% 08 KG-TOWER 数据面rating/design/revampPRO/II 工具六步取证而非猜扩展名 进阶09-12 ── 资产、标定、批量、落盘 09 FRI 资产边界对照而不复刻 10 关联式实现与标定对数插值幂律回归σ 修正E13 11 批量扫描工况矩阵内容寻址键断点续扫幂等 12 裕度判定四类裕度归一化binding三段式落盘 高级13-16 ── 选型、集成、误差、工程化 13 选型自动化方案族 × 塔径 × 负荷约束与代价分离多目标排序 14 与 Aspen/HYSYS 对接数据契约一次换算Column Analysis 的官方验证 15 不确定度CV 平方和开根MC 解析风险→设计点 16 工程化许可红线落成断言版本成对可复现检查 实战17-20 ── 闭环、比选、规模、工具包 17 端到端闭环六步填料段 dP101.4 Pa/m、泛点率 21.4%、Z2.50 m 18 两塔系比选同基准binding 比合格更有价值图表 19 平台化五层架构哈希分片缓存杠杆 3.2×瓶颈分布 20 工具包收官五层组合 8 项回归断言 交付清单三条贯穿全系列的主线纪律诚实边界铁律 1/2/3/4FRI 与 KG-TOWER 无公开 APIFRI 内容属会员权益KG-TOWER 许可禁逆向与派生二次开发只能走官方确证通道 公开关联式复现。单位与口径铁律 5/7内部统一 SI、换算只做一次Fp 必须先统一到 ft⁻¹上游物性与负荷必须同源同单位。可复现可审计铁律 6/8示例全部标注示例性建模关联式来源与单位集随结果落盘阈值版本化。二、完整代码与逐行剖析代码 2-1工具包核心打包与公共 API# -*- coding: utf-8 -*-fri_kt/__init__.py —— 公共 API 导出版本 0.1.0__version__0.1.0from.coreimport(Internals,Case,case_id,rate_tray,rate_packing,margins,LIMITS,flv,dp_flood_kister_gill,ergun_dp_per_m,n_og_absorption,tray_efficiency,fp_m_to_ft,INH2O_PER_FT_TO_PA_PER_M)# -*- coding: utf-8 -*-fri_kt/cli.py 片段 —— 命令入口rate/sweep/report/uncertainty/complianceimportargparse,json,sysfrom.coreimportCase,Internals,rate_tray,rate_packing,marginsfrom.sweepimportrun_sweepfrom.importreportasR INTERNALS{# 示例内件库真实几何库须来自产品手册/公开特性表/软件内件库IMTP#40:Internals(kindpacking,modelIMTP#40,a151.0,eps0.97,fp_ft_inv85.0),Pall50:Internals(kindpacking,modelPall50,a105.0,eps0.96,fp_ft_inv89.0),sieve-8mm-5%:Internals(kindtray,modelsieve-8mm-5%,dh8.0,hole_ratio0.05,C00.80,K232.0),valve-2pass:Internals(kindtray,modelvalve-2pass,dhNone,hole_ratio0.08,C00.90,K245.0),}defbase_case():returnCase(rhoV2.5,rhoL780.0,muV1.2e-5,muL3.0e-4,sigma0.02,Vm2.0,Lm4.0,D1.0,Csb0.075)defcmd_rate(args):cbase_case();itINTERNALS[args.internals]rrate_packing(c,it)ifit.kindpackingelserate_tray(c,it)mmargins(r)outdict(internalsit.model,**{k:(round(v,4)ifisinstance(v,float)elsev)fork,vinr.items()},**m)print(json.dumps(out,ensure_asciiFalse,indent2,defaultstr))return0ifm[ok]else2# 退出码即判据0 合格 / 2 越限逐段剖析__init__.py只导出公共 API并把__version__定在 0.1.0版本号是交付清单的第一项没有它用哪版重跑就无从谈起。INTERNALS注释再次强调真实几何库须来自产品手册/公开特性表/软件内件库——工具包不自带权威几何库这是第 09 篇边界纪律在代码里的延续。cmd_rate返回0 if m[ok] else 2把判据变成退出码。这样fri_kt rate可以直接挂在 CI 上实现设计一旦越限流水线即失败。反直觉点rate输出的 JSON 里warnings字段可能非空如Fp60 ft⁻¹但仍返回 0。这是刻意的——告警不等于失败是否把告警升级为失败应由使用方CI 配置决定而不是工具包替用户决定。代码 2-2回归测试8 项断言可直接运行# -*- coding: utf-8 -*-tests/test_regression.py —— 把关键数值钉死无需 pytest 即可运行importmath,os,sys sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.abspath(__file__))))importfri_ktasKdefapprox(a,b,tol1e-3):returnabs(a-b)tol*max(1.0,abs(b))deftest_fp_unit_and_flood_dp():assertapprox(K.fp_m_to_ft(79.0),259.19,1e-3)inh2o,pamK.dp_flood_kister_gill(85.0)# 入参 ft^-1assertapprox(inh2o,2.690,2e-3)andapprox(pam,2197.8,2e-3)deftest_ergun_and_flood_velocity():D1math.sqrt(4.0/math.pi)# 使塔截面积恰为 1 m^2cK.Case(rhoV2.5,rhoL780.0,muV1.2e-5,muL3e-4,sigma0.02,Vm6.0,Lm12.0,DD1,hL0.05)itK.Internals(kindpacking,modelIMTP#40,a151.0,eps0.97,fp_ft_inv85.0)rK.rate_packing(c,it)assertapprox(r[dP_dry_pam],697.9,3e-3)assertapprox(r[dP_total_pam],818.0,3e-3)assertapprox(r[flood_pct],61.0,3e-3)deftest_oconnell_units():assertapprox(K.tray_efficiency(2.5,0.30),41.7,5e-3)assertapprox(K.tray_efficiency(2.5,3e-4),22.1,5e-3)# 其余 4 项flv/tray_case/margins/uncertainty/compliance见完整文件defmain():fns[vfork,vinsorted(globals().items())ifk.startswith(test_)andcallable(v)]forfninfns:fn();print(f[PASS]{fn.__name__})print(f\n回归测试通过{len(fns)}/{len(fns)})if__name____main__:main()实测输出本机 numpy 2.2.6完整 8 项[PASS] test_compliance [PASS] test_ergun_and_flood_velocity [PASS] test_flv [PASS] test_fp_unit_and_flood_dp [PASS] test_margins_binding [PASS] test_oconnell_units [PASS] test_tray_case [PASS] test_uncertainty 回归测试通过 8/8逐段剖析所有断言都是数值而非函数不报错这是回归测试与冒烟测试的分界。反直觉点test_oconnell_units同时钉住 41.7% 与 22.1%——它防的不是算错而是单位被统一改掉第 05/14 篇。approx()用相对容差tol * max(1, |b|)而不是绝对容差既能在小量级如 0.11324上严格也能在大量级如 2197.8上合理。测试可python tests/test_regression.py直接运行不依赖 pytest也同时兼容 pytest函数名test_*、无副作用——降低第三方重跑的门槛。为什么这是最后一根钉子本项目 20 篇里所有数值结论2.690、0.1132、61.0%、41.7%、67.6%…都各自出现在某一篇中而回归测试把其中最关键的 8 组集中钉住。只要这 8 项通过读者就可以确信你手上的实现与系列中讨论的实现在口径上一致。代码 2-3CLI 全链路实测五条命令python-mfri_kt.cli rate IMTP#40 # 单点核算退出码 0/2 即判据python-mfri_kt.cli sweep--out_kt_sweep.csv python-mfri_kt.cli sweep--out_kt_sweep.csv# 再跑一次验证幂等python-mfri_kt.cli report# 宽表 操作窗口图python-mfri_kt.cli uncertainty# 风险 → 设计点python tests/test_regression.py# 8 项回归断言实测输出节选# rate IMTP#40片段 { internals: IMTP#40, dP_total_pam: 148.1948, dP_flood_inh2o: 2.6901, flood_pct: 25.8698, u_flood: 3.9374, binding: flood, ok: true } # sweep 两次 {total: 102, new: 102, skipped: 0, ok_new: 102} {total: 102, new: 0, skipped: 102, ok_new: 0} # uncertainty CV 0.1562 目标风险 5%: 设计点泛点率 67.6% (z1.645) 核验 P0.0496 目标风险 1%: 设计点泛点率 62.3% (z2.326) 核验 P0.0099 目标风险 10%: 设计点泛点率 70.8% (z1.282) 核验 P0.0993 # report 交付宽表 6 行 - _kt_delivery.csv 图形 - _kt_window.png逐段剖析rate在 D1.0 m 下泛点率 25.87%、bindingflood、oktrue注意它与第 17 篇D1.1 m、泛点率 21.4%数值不同——因为塔径不同。这提醒你任何结果都必须连同几何与工况一起引用case_id的存在理由。sweep两次首轮new102、续扫new0——幂等成立第 11 篇的机制在工具包里直接可用。uncertainty三个风险档位给出 67.6% / 62.3% / 70.8%蒙特卡洛核验概率分别约 4.96% / 0.99% / 9.93%——解析与数值一致说明正态近似在本 CV 下成立。report宽表 6 行内件 × 塔径组合的合格窗口 操作窗口 PNG。注意 PNG 内文字用英文——规避 matplotlib 默认字体缺中文字形的问题第 18 篇报错 3-4。三、常见报错与排查报错 3-1ModuleNotFoundError: No module named fri_kt。现象命令行找不到包。根因工作目录不在项目根或未安装。解法在项目根目录运行或用pip install -e .需一个最小pyproject.toml/setup.py测试脚本已自带sys.path注入见代码 2-2。报错 3-2CLIrate输出ok: false且退出码 2。现象流水线被判失败。根因该内件在基准工况下越限如筛板方案压降越限。这是正确行为。解法换内件或改几何第 13 篇的可行域搜索而不是改判据阈值。报错 3-3回归测试在某台机器上失败但代码没改。现象数值断言失败。根因多为依赖版本差异如 numpy 不同版本的对数/幂运算末位差异或本机默认浮点行为差异。解法断言用相对容差本工具包已如此1e-3~5e-3若仍失败记录两边的 numpy 版本并评估是否属平台差异绝不为了让测试通过而放宽到无意义如 10%。报错 3-4report生成的图里中文变方框、控制台刷UserWarning: Glyph ... missing。现象字体缺字形。解法图内用英文标签或显式设置支持中文的字体rcParams[font.sans-serif]并在交付说明里声明字体依赖。报错 3-5compliance报sources 含非公开来源。现象合规闸门拦截。根因把 FRI DRP 之类会员来源写进了sources。解法这正是设计意图第 09 篇边界表 第 16 篇白名单。把来源改为公开文献编号E1…E13 与 Ergun确需引用 FRI 时只能走公开文献中被引用的 FRI 数据路径。四、动手练习练习 1回归门禁运行python tests/test_regression.py。判定输出8 行[PASS]与回归测试通过 8/8退出码 0。练习 2CLI 全链路依次运行rate IMTP#40、sweep两次、report、uncertainty。判定得到binding: flood / ok: true两次 sweep 分别为new102与new0report输出交付宽表 6 行并生成 PNGuncertainty输出 67.6% / 62.3% / 70.8% 三档容差 ±0.5 个百分点。练习 3故意破坏口径看测试是否抓到把core.py里dp_flood_kister_gill的入参改成先乘 3.28084即把 ft⁻¹ 当 m⁻¹ 处理。判定test_fp_unit_and_flood_dp失败2.690 → 5.871并写出这正是回归测试要防的口径漂移要点数值全量平移、功能测试不报错。练习 4交付清单为你的项目写一份五件套交付清单。判定包含代码含版本号/依赖清单Python numpy/matplotlib 版本/来源清单公开编号/单位集内部 SI 与展示单位/阈值版本并说明缺任一件会导致什么歧义。五、小结与下一篇预告fri_kt0.1.0 收官五层组合核心/批量/报表/不确定度/合规每层可独立替换与测试、8 项回归断言8/8 通过把 Fp 口径、泛点压降、Ergun 压降、O’Connell 单位、塔板板压降、binding、CV、合规校验钉死、五条 CLI 命令rate/sweep/report/uncertainty/compliance其中 rate 的退出码即判据、以及五件套交付清单。三条最终纪律诚实边界无公开 API 就不写接口、单位与口径一次换算、显式标注、可复现可审计来源、单位与阈值随结果落盘。本系列到此结束。二十篇的共同结论是FRI 与 KG-TOWER 都不是可以编程调用的库而是必须被诚实对待的权威标尺——你无法调用它们但可以复现公开的经典关联式、建立自己的可审计引擎再用它们或其公开引用来标定与校验。这条路的门槛不在算法而在纪律单位、来源、版本、边界一样都不能少。本篇认知问题回显FAQQ1一个可发布的水力学核算工具包必须包含哪五个层A核心层数据模型 Internals/Case 核算 rate_tray/rate_packing 裕度 margins纯函数、不做 I/O、批量层内容寻址 case_id 断点续扫 长表落盘、报表层宽表交付 三段元数据 操作窗口图、不确定度层CV 平方和开根 蒙特卡洛 解析反解设计点、合规层清单校验 版本成对 来源白名单 受限关键词扫描。边界的意义在于核心层是纯函数才可缓存、可并行、可回归。Q2为什么回归测试是这类工具包的最后一根钉子钉住哪些数值A因为它挡住的是最危险的一类错误——“改动某处后所有结果平移了一点”这种口径漂移不会被任何功能测试发现却会让历史结论与新结论不可比。8 项断言钉住fp_m_to_ft(79)259.19与dp_flood(85 ft⁻¹)2.690 inH₂O/ftFp 口径、FLG(12,6,780,2.5)0.11324、Ergun 干/湿压降 697.9/818.0 Pa/m 与泛点率 61.0%、Eo(2.5,0.30)41.7%与Eo(2.5,3e-4)22.1%黏度单位、塔板泛点率 77.0% 与板压降 255.1 mm、bindingdP、CV0.1562 与设计点 67.6%、合规校验条数。Q3CLI 应暴露哪些命令才能覆盖从单点到平台A五条rate 内件单点核算退出码即判据合格 0 / 越限 2可直接做 CI 门禁、sweep --out批量扫描支持断点续扫与幂等、report宽表 操作窗口图交付、uncertainty风险→设计点反解、compliance --manifest合规闸门。设计要点是入口要可被判定的而非只打印的。Q4交付清单应包含什么才能让第三方重跑A五件套代码含版本号本工具包为 0.1.0、依赖清单Python 版本 numpy 2.2.6 / matplotlib 3.10.8、来源清单公开关联式编号 E1/E2/E5/E7/E8/E9/E11 Ergun、单位集内部统一 SI压降 Pa/m 与 mm 液柱并列展示Fp 存储用 ft⁻¹、阈值版本含版本号与调整历史。少任一件重跑都会有歧义。Q5回顾全系列哪些是铁律、最佳实践、经验法则A铁律8 条不可违反FRI/KG-TOWER 无公开 API 不得臆造接口KG-TOWER 官方互操作只有 PRO/II 工具许可禁止逆向/派生/向竞品分发输出FRI 内容属会员权益不得复制单位必须显式且换算一次示例必须标注示例性建模上游物性与负荷必须同源同单位关联式来源与单位集必须随结果落盘。最佳实践先向量化再并行先约束后排序缓存键必须完备片级幂等 原子落盘图 表一起给阈值版本化。经验法则泛点率≤85%、操作/漏液比≥1.5、压降≤200 mm 液柱、Fp60 ft⁻¹ 需警觉、设计点泛点率按风险反解5% 风险 → 约 67.6%。