:第一个可运行的自动化算例——三场景 + 批量运行 + Excel 取数一条龙)
AFT二次开发教程03第一个可运行的自动化算例——三场景 批量运行 Excel 取数一条龙版本与事实声明产品与版本AFT Fathom 15 / AFT Impulse 12当前本篇操作细节引用官方Fathom 13帮助文档正文菜单项与行为在版本间稳定当前版界面以官方文档为准。语言/环境Python 3.xpandas openpyxlAFT Fathom 桌面端 Excel。本文目标读完能独立跑完三个工况 → 一次批跑 → 一份结构化结果表的最小闭环并留下可对账的基准值。所有水力数值为示例性建模不代表任何标准规定亦不对应任何真实装置。许可与价格以 Datacor 官方渠道为准。一句话结论AFT 最小可用自动化闭环 在Scenario Manager里把 N 个工况建成同一模型文件内的场景 用Excel Export ManagerFile 菜单预先指定导出到哪张表的哪个单元格 用File Start Batch Run选Scenarios in Current Model后台批跑并勾选Save Using Excel Export Manager最后用 pandas 读回导出工作簿——这条闭环的产物就是你后续所有脚本的对账真值。〇、本篇要解决的认知问题Q1Scenario Manager、Start Batch Run、Excel Export Manager 三者的正确使用顺序是什么顺序错了会怎样Q2为什么一个工况一个.fth文件是反模式同一文件内多场景好在哪Q3Excel Export Manager 里Excel Starting Cell / Excel Ending Cell两个字段为什么是防错设计Q4批跑模式下的 Excel 导出与手工单跑时有什么官方明确的行为差异Q5怎么为一个自动化结果建立手工基准线并在后续脚本里持续对账一、机制解析3.1 三件套的正确顺序这一步最容易做反把三件套当柱子正确施工顺序是① 建场景树 ② 配导出项 ③ 批跑 ④ 取数对账 Scenario Manager → Excel Export → Start Batch Run → pandas 读回 (先有工况骨架) Manager(先备好出口) (一次跑完所有场景) (落成长表)为什么导出项必须排在批跑之前官方原文明确“The Excel Export option can only be chosen if the batch run type is for Scenarios in Current Model.Additionally, the desired output must first be configured in the Excel Export Managerunder the File menu for any data to be exported.” 翻译成人话批跑对话框里那个Save Using Excel Export Manager开关只有在 Excel Export Manager 里已经配好导出项时才有意义。先批跑、后配导出 白跑一遍。为什么先建场景树Batch Run Type里选Scenarios in Current Model的前提是当前模型有场景官方还补了一句——如果当前模型没有场景就只有Models from Different Files这一种类型可选。也就是说场景树决定了你有没有资格用最省事的那种批跑方式。3.2 为什么不一工况一文件组织方式文件系统继承与复用官方对比能力结论一工况一.fthN 个文件容易版本错乱无只能靠Export Model Data出.inp文本手工 diff反模式同文件多场景1 个.fthlinked 属性跨代继承Scenario Comparison Tool / Grid推荐官方对 Scenario Manager 的能力描述里Pass changes from a scenario to its variants把改动从一个场景传递到其变体与See what scenarios have output by automatically changing the text color to blue if they have output有输出的场景文字自动变蓝这两条恰恰是一工况一文件永远得不到的。前者让你的改一个共同参数变成一次操作后者让你一眼看出哪个场景还没跑出结果——批跑前肉眼 QA 极其好用。3.3 Starting/Ending Cell一个被低估的防错设计Excel Export Manager 每一项row都定义数据导去哪Excel Sheet目标表名Excel Starting Cell左上角单元格Excel Ending Cell自动推算的右下角。官方对 Ending Cell 的说明是“The automatically calculated lower-right cell of the data…It is important to recognize that the Excel Starting Cells can be defined in a way that data gets overwritten. The Ending Cell column is a handy reference to help avoid this.”翻译起始单元格是可以互相压塌的——你把两项都指向A1第二项就把第一项盖了。Ending Cell 是给你**核对这一块占多大地方**用的。所以 Excel Export Manager 界面下方还有一个网格preview专门显示重叠区域。这就是为什么导出前先目检重叠是必须动作也是第 06 篇要写冲突检测脚本的原因。3.4 批跑模式的行为差异官方两条官方在Exporting To Excel页专门用一节讲多场景导出的区别铁律 9 的来源工作簿粒度If multiple sheets are specified in the Excel Export Manager, the only way to export multiple scenarios is toexport every scenario to its own Workbook. To keep data from multiple scenarios in one Workbook,there can only be one sheetspecified.保存时机the Excel File will be saved after each scenario.In normal single-scenario exports the file is never saved, but in batch mode it is required.含义手工单跑导数是不自动保存的你得自己在 Excel 里存批跑模式下每个场景跑完就强制保存一次。这带来两个工程后果(a) 你机器上会真的出现那个文件不用手动存(b) 如果你在批跑中途把那个工作簿用 Excel 打开着改可能撞上文件锁——批跑期间不要打开目标工作簿。还有一条隐藏福利Batch Run 里有Export Only (Do Not Run)选项可以只导出、不重跑复用已有输出。官方同时提醒如果某个场景没有输出Export Only 不会为它导出任何数据因为不运行就不产生输出。3.5 手工基准线的价值在你机器、你版本、你流体库下人肉跑出来的这组结果是后续一切自动化的回归基准regression baseline。第 09 篇的扫描、第 17 篇的端到端项目验收方式都是脚本复现基准工况误差在导出精度内一致。没有基准批量结果错到多远你都不知道。二、完整代码与逐行剖析本篇代码分两段一段规划场景表把工况设计成数据结构天然可复用一段读回导出件把 Excel 导出工作簿变成(scenario, object, parameter, unit, value)长表。两段都自带--selftest不依赖 AFT 即可验证链路。代码 3-1scenario_plan.py工况骨架的数据化# -*- coding: utf-8 -*- scenario_plan.py —— 把要跑几个工况、每个改什么写成可校验的数据结构。 这是第 09 篇参数扫描的前身先有规划的骨架再有变更表。 运行python scenario_plan.py --selftest importjsonimportsys# 场景路径名遵循官方全限定格式例Base Scenario\\US Units\\Pump ASCENARIO_PLAN{model:demo_network.fth,# 示例性文件名base_path:rBase Scenario\US Units,# 全限定前缀铁律5scenarios:[{name:Pump A Only,changes:{P3.Fixed Speed (%):100.0}},{name:Pump B Only,changes:{P3.Fixed Speed (%):0.0,P4.Fixed Speed (%):100.0}},{name:Pump AB,changes:{P4.Fixed Speed (%):100.0}},],}deffull_path(scn_name:str)-str:拼出全限定 Scenario Path Name跨场景变更必须用它否则报场景名不唯一。returnSCENARIO_PLAN[base_path]\\scn_namedefvalidate(plan:dict)-list:校验场景名唯一、路径前缀非空、每个场景至少一处变更。返回问题列表。problems,seen[],set()ifnotplan.get(base_path):problems.append(base_path 为空跨场景变更必须用全限定路径名)forsinplan.get(scenarios,[]):ifs[name]inseen:problems.append(f场景名重复{s[name]})seen.add(s[name])ifnots.get(changes):problems.append(f场景{s[name]}没有任何变更属空场景)returnproblemsdefselftest():problemsvalidate(SCENARIO_PLAN)assertproblems[],problemsassertfull_path(Pump A Only)rBase Scenario\US Units\Pump A Only# 故意制造一个重复场景验证校验器能抓到badjson.loads(json.dumps(SCENARIO_PLAN))bad[scenarios].append({name:Pump A Only,changes:{X:1}})assertvalidate(bad),重复场景名应被检出print(SELFTEST OK规划校验器工作正常正例通过、反例被拒。)print(json.dumps(SCENARIO_PLAN,ensure_asciiFalse,indent2))if__name____main__:if--selftestinsys.argv:selftest()逐行剖析SCENARIO_PLAN把工况设计从 GUI 操作里抽出来变成数据结构这是本系列的贯穿手法先在代码里定义工况再去 GUI 落实。好处是工况可以 diff、可以 review、可以自动生成变更表。full_path()直接实现铁律 5。官方原文给的示例正是Base Scenario\US Units\Pump A这种反斜杠分隔的层级路径——注意在 Python 里用 raw stringr...或双反斜杠否则\U会被解释成 Unicode 转义报错这也是真实踩过的坑见报错 3-3。validate()的三条校验路径非空、场景名唯一、非空场景分别对应官方 Excel 导入错误表里的Scenario name is not unique、Scenario not found in the model和空场景白跑两类浪费。selftest()用复制一份故意加坏数据的写法验证校验器真的会拒绝——这是测试的正确姿势只测正例是自欺。代码 3-2read_export.pyExcel 导出件 → 长表# -*- coding: utf-8 -*- read_export.py —— 读取 Excel Export Manager 产物含多场景→ 标准长表 输出列scenario, object, parameter, unit, value 运行 python read_export.py --selftest python read_export.py export.xlsx --sheet Output --out long.csv importargparseimportioimportreimportsysimportpandasaspd UNIT_REre.compile(r^\s*(?Pname.*?)\s*(?:\[(?Punit[^\]])\])?\s*$)# Pressure [psia]defsplit_unit(col:str):mUNIT_RE.match(str(col))return(m.group(name).strip(),(m.group(unit)or).strip())ifmelse(str(col).strip(),)defread_any(path:str,sheetNone)-pd.DataFrame:xlsx/csv 通吃读 CSV 一律 utf-8-sigVBA/Excel 产物常带 BOM。ifpath.lower().endswith((.xlsx,.xlsm)):returnpd.read_excel(path,sheet_namesheetor0,engineopenpyxl)returnpd.read_csv(path,encodingutf-8-sig,dtypestr)defto_long(df:pd.DataFrame,scenario_colNone,object_colNone)-pd.DataFrame:宽表首列对象其余参数[单位]→ 长表。dfdf.rename(columnslambdac:str(c).strip())object_colobject_colordf.columns[0]scenario_colscenario_color(ScenarioifScenarioindf.columnselseNone)recs[]forcolin[cforcindf.columnsifcnotin(object_col,scenario_col)]:name,unitsplit_unit(col)for_,rowindf.iterrows():ifpd.isna(row[object_col]):continuerecs.append({scenario:(str(row[scenario_col]).strip()ifscenario_colelseBase Scenario),object:str(row[object_col]).strip(),parameter:name.lower().replace( ,_),unit:unit,value:row[col],})longpd.DataFrame(recs,columns[scenario,object,parameter,unit,value])long[value]pd.to_numeric(long[value],errorscoerce)# N/A/— → NaN 而不崩returnlongdefselftest():demo(Scenario,Junction,Pressure [psia],Flow [gpm]\nPump A Only,P3,120.5,500.0\nPump B Only,P3,118.2,498.6\nPump A Only,P4,121.0,502.1\n)dfpd.read_csv(io.StringIO(demo),dtypestr)longto_long(df,scenario_colScenario,object_colJunction)assertlen(long)6,len(long)# 3 行 × 2 参数assertsorted(long[scenario].unique())[Pump A Only,Pump B Only]assertset(long[unit]){psia,gpm}print(SELFTEST OK3 行 × 2 参数 6 行长表场景与单位列解析正确。)print(long.to_string(indexFalse))defmain():apargparse.ArgumentParser()ap.add_argument(path,nargs?)ap.add_argument(--sheet,defaultNone)ap.add_argument(--out,defaultlong.csv)ap.add_argument(--selftest,actionstore_true)aap.parse_args()ifa.selftestornota.path:selftest()return0longto_long(read_any(a.path,a.sheet))long.to_csv(a.out,indexFalse,encodingutf-8-sig)print(f对象{long[object].nunique()}个参数{long[parameter].nunique()}个f场景{long[scenario].nunique()}个共{len(long)}行 →{a.out})return0if__name____main__:sys.exit(main())逐行剖析UNIT_RE把列名拆成名称 单位单位随行入库。这是消灭裸数静默错误的关键——你永远不知道一个孤零零的120.5是 psia 还是 bar除非它旁边跟着单位。read_any对 xlsx 走 openpyxl、对 CSV 走utf-8-sig与第 11 篇的落盘契约一致。to_long里scenario_col默认找Scenario列Excel Export Manager 的导出件在配置了Other类型 / Export Guide 时可能带场景名列没有就归到Base Scenario保证长表 schema 恒定。pd.to_numeric(errorscoerce)把N/A、—、空串统一变 NaN 而不抛异常——导出件里这些符号很常见管线必须容忍。selftest()断言len(long) 63 行 × 2 参数。给你一个可量化的判定读者改代码后重跑自检数字不对立刻发现。三、常见报错与排查报错 3-1批跑对话框里Save Using Excel Export Manager是灰的选不了。现象想批跑直接导 Excel选项不可点。根因两个官方前提缺一不可——(a)Batch Run Type必须是Scenarios in Current Model(b)必须先在 Excel Export Manager 里配好导出项铁律导出项先于批跑。解法先 File Excel Export Manager 建至少一项并确认 Ending Cell 不与他人重叠再开批跑。报错 3-2多场景导出后工作簿里只剩最后一个场景的数。现象明明跑了三个场景导出件只有一份结果。根因Excel Export Manager 里指定了多个工作表而官方规定多 sheet 多场景只能每场景一个独立工作簿。解法要么只指定一个 sheet让所有场景进同一工作簿要么接受每场景一个工作簿并在第 12 篇用聚合脚本合并。报错 3-3Python 里写Base Scenario\\US Units报 Unicode 相关错误。现象UnicodeDecodeError或SyntaxWarning: invalid escape sequence \U。根因\U是 Python 的 Unicode 转义前缀常规字符串里直接写会出问题。解法用 raw stringrBase Scenario\US Units或双反斜杠。官方示例的场景路径正是这种反斜杠层级结构。报错 3-4批跑到一半打开目标 Excel 工作簿导致导出报错/文件被锁。现象某个场景后开始报写入失败。根因批跑模式下每个场景跑完就保存一次目标工作簿此时若你正用 Excel 打开它就撞上文件锁。解法批跑期间不要打开目标工作簿要看进度就等批跑结束。报错 3-5手工单跑导出后去找文件找不到。现象单跑导出后磁盘上没有那个 xlsx。根因官方明确Excel Export Manager does not save Excel files for non-batch run exports——单跑导出不自动保存需你手动在 Excel 里存。解法单跑时导出后立即另存为或干脆用批跑就能自动保存。四、动手练习练习 1场景骨架按代码 3-1 的结构为你自己的或示例的模型设计 3 个场景每个至少一处参数变更。判定python scenario_plan.py --selftest输出SELFTEST OK且你手写的base_path符合Base Scenario\单位制\工况名层级。练习 2跑通闭环在 AFT 里落实三个场景 → 配 1 项 Excel Export →Start Batch Run后台跑 → 得到导出工作簿。判定导出工作簿的三个场景都有数据Excel Export Manager 的 Ending Cell 与起始单元格无重叠界面网格无红色重叠区。练习 3读回对账跑python read_export.py 你的导出件.xlsx --out long.csv。判定长表行数 对象数 × 参数数 × 场景数写出你的乘法式unit列无空值或空值行都能解释为无单位参数。练习 4手工基准挑一个基准场景把关键结果值记入笔记并标注示例性建模。判定至少 5 个关键值入库且后续你任何脚本跑同一场景时这些值能对回到导出精度内。五、小结与下一篇预告本篇跑通了 AFT 自动化的最小闭环场景骨架数据化 → Excel Export Manager 先备好出口 → Start Batch Run 后台批跑 → pandas 读回长表。三条必须记住的机制导出项必须先于批跑配好、多 sheet 多场景只能每场景独立工作簿、批跑模式下工作簿每场景保存一次单跑不保存。你现在有了第一份手工基准线。第 04 篇《工程模型文件与对象模型》我们钻进底层——四种模型扩展名.fth/.aro/.imp/.xtr与*.bakX-001备份级联机制、为什么模型文件虽是分节文本但绝不能手改官方报错原文为证以及从 AFT Transfer 参数表反推出的Pipe 与 Junction 对象类型全景。FAQ与第〇节一一对应Q1Scenario Manager、Start Batch Run、Excel Export Manager 的正确使用顺序A先建场景树Scenario Manager再配导出项Excel Export Manager再批跑File Start Batch Run选 Scenarios in Current Model 并勾 Save Using Excel Export Manager最后读回导出件顺序反了会白跑一遍因为批跑对话框的 Excel 导出开关只有在已配置导出项时才可用。Q2为什么一个工况一个 .fth 文件是反模式A因为同文件多场景能拿到 Scenario Manager 独有的 linked 属性跨代继承与 Scenario Comparison 对比能力还能用文字变蓝一眼看出哪些场景有输出一工况一文件则文件系统易乱、无继承、只能靠导出 .inp 文本手工 diff。Q3Excel Starting Cell 与 Ending Cell 是什么作用AStarting Cell 指定数据导到的左上角单元格Ending Cell 是自动推算的右下角单元格官方明确起始单元格可被定义成互相覆盖Ending Cell 与界面预览网格就是用来避免数据被覆盖、检查重叠区域的。Q4批跑模式下的 Excel 导出与单跑有什么官方差异A两点若指定多个工作表多场景导出只能每场景一个独立工作簿要进同一工作簿只能指定一个 sheet批处理模式下 Excel 文件会在每个场景跑完后保存单场景导出则不保存因此批跑期间不要打开目标工作簿。Q5怎么为自动化结果建立并持续对账的手工基准线A在你自己的机器和版本下手工跑一个基准场景记录关键结果值并标注示例性建模此后一切脚本的验收方式都是复现基准工况、误差在导出精度内一致本篇的 read_export.py 长表就是把结果对账的数据底座。