水力仿真结果准确性验证工具。将 MCP 仿真引擎输出的结果文件(CSV / XLSX)与历史实测 Excel 数据进行对比, 计算误差统计指标(RMSE、MAE、最大偏差、相关系数等),生成对比曲线图和验证报告。 当用户提到以下内容时触发:仿真验证、结果对比、精度验证、仿真 vs 实测、accuracy validation、 误差分析、RMSE、对比曲线、仿真准确性、历史数据对比、节制闸数据对比、验证仿真结果。 即使用户只是说"对比一下结果"、"看看仿真准不准"、"和实测数据比一下",也应触发此 skill。
本 skill 将 MCP 仿真引擎输出的时序结果文件(CSV / XLSX)与历史实测数据(Excel)进行对比,验证仿真精度。整个流程分为 4 个阶段。
始终使用 中文 与用户沟通。
结果文件来自 hydros-engine-simulation-skill 的阶段五输出,或通过 get_timeseries_data MCP 工具获取。
关键字段:
| 字段 | 说明 |
|---|---|
object_name | 对象名称,如 QD-5#断面#001、ZM1-节制闸#1、FSK2-北易水退水闸 |
object_type | CrossSection(断面)、Gate(闸门)、DisturbanceNode(分水口/退水闸) |
metrics_code | water_level、water_flow、 |
gate_openingdata_index | 仿真步序号(从 1 开始) |
value | 数值 |
时间转换:仿真步到实际时间的转换需要 step_resolution(秒/步)。如果结果文件中没有此信息,向用户询问。常见值为 120 秒/步。仿真起始时间通常为 biz_start_time(如 2025/01/01 00:00:00)。
Excel 文件包含多个 Sheet,每个 Sheet 代表一个节制闸。
标准列结构:
| 列 | 对应 MCP 指标 |
|---|---|
| 日期 | 时间戳 |
| 闸前水位 | water_level(闸前) |
| 闸后水位 | water_level(闸后) |
| 1~4号闸门开度 | gate_opening(单位可能是 mm,需要转换) |
| 流量 | water_flow |
Excel 还可能包含分水口/退水闸流量列(名称不固定,位于流量列之后)和设计水位列。
pandas 读取 MCP 仿真结果文件:.csv 用 pd.read_csv(...),.xlsx 用 pd.read_excel(..., sheet_name=0)openpyxl 或 pandas 读取 Excel 各 Sheet:pd.read_excel(excel_path, sheet_name=None)step_resolution(默认 120s)MCP 仿真对象和 Excel Sheet(节制闸)之间的对应关系必须优先通过 MDM 元数据 建立,不能默认用静态映射表或直接用仿真对象名猜测。
对于每个历史 Excel Sheet:
倒虹吸出口节制闸、渡槽进口节制闸、节制闸 等后缀。hydros-engine-mdm.fetch_gate_info(waterway_id, station_name) 查询闸站。station_front_section:闸前断面station_back_section:闸后断面object_id 到仿真结果 Excel 中精确匹配 object_id。metrics_code 读取 water_level / water_flow。闸前水位、闸后水位、流量。匹配规则(按优先级):
station_front_section.object_id / station_back_section.object_id 命中仿真结果 object_id,置信度最高。object_name。闸前水位、闸后水位、流量;只有精确列名不存在时,才允许用 上游水位、下游水位、过闸流量 等别名兜底。| Excel 列 | MCP metrics_code | 说明 |
|---|---|---|
| 闸前水位 | water_level | MDM station_front_section 的水位 |
| 闸后水位 | water_level | MDM station_back_section 的水位 |
| 流量 | water_flow | 默认使用 MDM station_front_section 的断面流量 |
| N号闸门开度 | gate_opening | 注意单位:Excel 可能是 mm,MCP 可能是 m |
以 markdown 表格展示匹配结果,让用户确认或修正:
| 序号 | Excel Sheet | MCP 对象 | 匹配指标 | 置信度 |
|------|------------|---------|---------|--------|
| 1 | 北易水倒虹吸出口节制闸 | FSK2-北易水退水闸 | water_level, water_flow | 高 |
| 2 | 北拒马 | FSK6-北拒马退水闸 | water_level, water_flow | 高 |
| 3 | 沙河(北)倒虹吸出口节制闸 | (待确认) | - | 低 |
用户确认后进入数据质量检查。
优先使用 scripts/build_mdm_gate_map.py 生成映射文件。该脚本以当前仿真结果为入口,读取 waterway_id / biz_scenario_id,用 MDM 水网模型中的 GateStation 过滤当前仿真实际存在的闸前/闸后断面,再从历史 Excel 全量 Sheet 中反查观测 Sheet,避免把不属于当前仿真范围的历史 Sheet 引入对比。
典型流程:
python3 scripts/build_mdm_gate_map.py \
--simulation-file SIM_TASK.xlsx \
--history-excel 节制闸数据.xlsx \
--mdm-model objects.yaml \
--output mdm_gate_map.json \
--diagnostics mapping_diagnostics.csv
python3 scripts/forebay_water_level_report.py \
SIM_TASK.xlsx \
节制闸数据.xlsx \
output_dir \
--mdm-map-json mdm_gate_map.json
在进行对比计算之前,必须先检查两边数据是否存在恒定不变的情况。恒定数据意味着仿真未真正运行或传感器故障,对比没有意义。
仿真引擎可能因为初始化问题、边界条件缺失或智能体未响应,导致某些对象的输出值在整个仿真过程中完全不变(方差为 0)。如果不检测就直接算 RMSE/NSE,会得到误导性的结果——比如一个恒定值恰好接近实测均值,NSE 看起来还不错,但实际上仿真根本没有动态响应。
对每个匹配的对象-指标组合,分别检查仿真侧和实测侧:
| 检测项 | 判定条件 | 处理方式 |
|---|---|---|
| 仿真值恒定 | 方差 = 0 或 max - min < 1e-6 | 标记为 SIM_CONSTANT,在报告中警告,跳过 NSE 计算(NSE 对恒定值无意义) |
| 实测值恒定 | 方差 = 0 或 max - min < 1e-6 | 标记为 OBS_CONSTANT,可能是传感器故障或停机期间,建议换时间段 |
| 仿真值全为 0 | 所有值 = 0 | 标记为 SIM_ZERO,说明该对象在仿真中未激活(如退水闸关闭),单独列出 |
| 仿真值近似恒定 | 标准差 / 均值 < 0.1%(变异系数极小) | 标记为 SIM_NEAR_CONSTANT,提示用户关注 |
std, min, max, mean## 数据质量检查
| 对象 | 指标 | 数据源 | 问题 | 详情 |
|------|------|--------|------|------|
| FSK2-北易水退水闸 | water_flow | 仿真 | SIM_ZERO | 所有值为 0,退水闸未激活 |
| ZM1-入口断面 | water_level | 仿真 | SIM_NEAR_CONSTANT | std=0.002, CV=0.003% |
SIM_CONSTANT 或 SIM_ZERO 的组合,仍然生成对比图表(方便用户直观看到问题),但在误差统计表中标注"不适用"而非给出误导性的 NSE 值| 原因 | 表现 | 建议 |
|---|---|---|
| 退水闸/分水口未激活 | flow = 0 恒定 | 检查仿真场景配置中该对象是否被启用 |
| 边界条件缺失 | 水位恒定在初始值 | 检查上游/下游边界条件是否正确加载 |
| 智能体未响应 | 闸门开度恒定 | 检查闸站智能体是否正常运行 |
| 仿真步数不足 | 前几步恒定,后面才变化 | 增加仿真步数或检查预热期 |
| 历史数据停机 | 实测值恒定 | 换一个有正常运行数据的时间段 |
仿真时间(如 2025/01/01 起)和历史实测时间(如 2017~2024)通常不在同一时间窗口。采用以下策略之一(询问用户选择):
对每一对匹配的对象-指标组合,使用 scripts/compare_timeseries.py 计算:
| 指标 | 公式 | 说明 |
|---|---|---|
| RMSE | √(Σ(sim-obs)²/n) | 均方根误差,越小越好 |
| MAE | Σ | sim-obs |
| Max Deviation | max( | sim-obs |
| MAPE | Σ( | sim-obs |
| R² | 1 - Σ(sim-obs)²/Σ(obs-mean)² | 决定系数,1.0 为完美拟合 |
| NSE | 1 - Σ(sim-obs)²/Σ(obs-mean)² | Nash-Sutcliffe 效率系数(水文领域常用) |
| Bias | mean(sim) - mean(obs) | 系统偏差(正=仿真偏高,负=仿真偏低) |
scripts/compare_timeseries.py)对每一对匹配的对象-指标,生成:
输出目录必须参考 hydros-engine-skill-executor 的层级组织,不再把 HTML、payload、CSV 平铺在 output_dir 根目录:
| 子目录 | 内容 |
|---|---|
report/ | validation.html 等可直接打开或上传的报告文件 |
data/ | mdm_gate_validation_payload.json、mdm_gate_validation_metrics.csv、映射诊断等数据产物 |
charts/ | 后续如生成 PNG/SVG 图表时统一放入该目录 |
如果旧版本已在根目录生成 validation.html、mdm_gate_validation_payload.json、mdm_gate_validation_metrics.csv,重新生成时应清理这些旧平铺产物,避免用户误打开过期文件。
验证报告页面模板必须沉淀在 assets/validation-report-template/index.html。生成脚本负责读取模板并替换占位符,避免把整页 HTML/CSS/JS 长期硬编码在脚本里。
当前规范:生成的 report/validation.html 采用 数据内联,即在 HTML 内直接写入报告 payload,保证单文件可打开和可上传。assets/validation-report-template/validation.data.js 仅作为未来外置数据模式的保留文件,当前不要在 HTML 中引用,也不要要求用户额外携带该文件。
报告中的长表必须提供分类过滤:误差统计表至少支持按指标和结果判断过滤,映射诊断表至少支持按指标和匹配结果过滤,数据质量检查表至少支持按指标和数据提示过滤。报告面向业务人员时,表头和单元格不要直接暴露 MDM_OBJECT_ID、SIM_NEAR_CONSTANT、OBS_COLUMN_MISSING 等内部状态码,应转换为“按仿真断面编号匹配”“仿真变化过小”“缺少实测列”等通俗中文。
生成 output/validation/validation_report.md(或 Word),包含:
| 用户说 | 动作 |
|---|---|
| "对比仿真结果" / "验证精度" | 从阶段一开始,让用户提供两个文件 |
| "这两个文件对比一下" | 从阶段一开始,识别文件格式自动分配 |
| "匹配结果不对" / "修正映射" | 回到阶段二重新匹配 |
| "换个时间段" / "重新对齐" | 回到阶段三调整时间 |
| "只看图表" / "生成报告" | 跳到阶段四 |
pandas, openpyxl, matplotlib, numpypip3 install pandas openpyxl matplotlib numpy --break-system-packages 或使用 venvhydros-engine-simulation-skill以下是已知的 MCP 仿真对象与中线工程节制闸的映射关系(持续更新):
| MCP 对象 | object_type | Excel Sheet | 可对比指标 | 备注 |
|---|---|---|---|---|
| ZM1-入口断面 | CrossSection | 北易水倒虹吸出口节制闸 | water_level ↔ 闸前水位, water_flow ↔ 流量 | ZM1 节制闸的上游断面 |
| ZM2-入口断面 | CrossSection | 坟庄河倒虹吸出口节制闸 | water_level ↔ 闸前水位, water_flow ↔ 流量 | ZM2 节制闸的上游断面 |
| FSK2-北易水退水闸 | DisturbanceNode | 北易水倒虹吸出口节制闸 | water_level ↔ 闸前水位 | water_flow 常为 0(退水闸未激活),对比流量无意义 |
| FSK6-北拒马退水闸 | DisturbanceNode | 北拒马 | water_level ↔ 闸前水位 | water_flow 常为 0 或极小值 |
| 对象 | 指标 | 问题 | 说明 |
|---|---|---|---|
| FSK2-北易水退水闸 | water_flow | SIM_ZERO | 仿真中退水闸关闭,流量恒为 0 |
| FSK6-北拒马退水闸 | water_flow | SIM_NEAR_CONSTANT | 流量接近 0(~0.5 m³/s),与实测差异大 |
| ZM1-节制闸#1/#2 | gate_opening | 无实测对照 | Excel 中闸门开度单位为 mm,MCP 为 m,且 ZM 对象只有 gate_opening 无 water_level |
| ZM2-节制闸#1/#2 | gate_opening | 无实测对照 | 同上 |
当匹配到新的对应关系或发现新的数据质量问题时,应更新此表。