# SystemSimulationApp SystemSimulationApp 是一个面向系统仿真的可视化建模原型。当前项目已经具备两条基础能力: - 使用 FastAPI 嵌入 draw.io,提供可视化拖拽建模界面。 - 使用 `PythonModels` 中已有的 Python 仿真模型,运行当前固定拓扑的 `TestModelSystem`。 下一阶段的目标是把这两条能力接起来,先完成一个小 MVP: ```text draw.io 画图 -> 解析 draw.io XML -> 生成 SystemModel -> 映射到 PythonModels.TestModelConfig -> 调用 run_testmodel() -> 返回并展示仿真结果 ``` ## 当前状态 ### 已有前端和接口基础 - `app/main.py`: FastAPI 主入口。 - `app/static/index.html`: 当前 draw.io iframe 页面。 - `/api/component-library.drawiolib`: 当前 draw.io 自定义组件库接口。 - `/api/system-xml`: 当前 draw.io XML 到简单系统 XML 的导出接口。 - `/drawio/`: FastAPI 到 draw.io Docker 的同源代理入口。 ### 已有 Python 仿真模型 `PythonModels` 目录里已经有一套 Python 仿真骨架: ```text PythonModels/components/ cylinder.py -> Cylinder,端口 port_b tank.py -> Tank,端口 port_a pipe.py -> Pipe,端口 port_a / port_b orifice.py -> Orifice,端口 port_a / port_b tee.py -> Tee,端口 port_in / port_out1 / port_out2 PythonModels/core/ network.py -> SimulationNetwork / Connection ports.py -> PortState solver.py -> integrate_ode / SolveIVPConfig PythonModels/systems/ testmodel.py -> 当前唯一可运行系统 TestModelSystem ``` 当前 `TestModelSystem` 支持的是固定拓扑: ```text mycylinder -> mytee -> myorifice -> mypipe -> myorifice1 -> mypipe1 -> mytee1 -> mytank ``` 因此第一版不要做任意拓扑仿真,而是先把 draw.io 中画出的这个固定拓扑映射到现有 `TestModelSystem`。 ## 核心原则 不要让仿真逻辑直接依赖 draw.io XML。 推荐分层: ```text draw.io XML -> SystemModel -> PythonModels adapter -> PythonModels runner -> SimulationResult ``` 其中: - draw.io XML 只是可视化画布格式。 - `SystemModel` 是系统仿真的核心结构化数据。 - PythonModels adapter 负责把 `SystemModel` 转成 `TestModelConfig / TestModelRunConfig`。 - 仿真器只认结构化模型,不直接解析画布。 这样后续即使替换 draw.io,仿真层也不用推倒重来。 ## MVP 范围 第一版只支持当前 `TestModelSystem` 对应的拓扑: ```text cylinder -> tee -> valve/orifice -> pipe -> tee -> tank -> valve/orifice -> pipe -> ``` 第一版支持的组件: | draw.io 类型 | PythonModels 类型 | 配置对象 | 端口 | | --- | --- | --- | --- | | `cylinder` | `Cylinder` | `CylinderConfig` | `port_b` | | `tank` | `Tank` | `TankConfig` | `port_a` | | `pipe` | `Pipe` | `PipeConfig` | `port_a`, `port_b` | | `valve` / `orifice` | `Orifice` | `OrificeConfig` | `port_a`, `port_b` | | `tee` | `Tee` | 暂无独立配置 | `port_in`, `port_out1`, `port_out2` | 前端可以继续显示“阀门”,但底层建议使用: ```xml modelType="orifice" ``` 因为 PythonModels 里实际对应的是 `Orifice`。 ## SystemModel 设计 建议新增统一结构: ```json { "name": "testmodel_from_drawio", "components": [ { "id": "mycylinder", "type": "cylinder", "role": "cylinder", "parameters": { "volume": 0.01, "p0": 35000000, "T0": 300 } } ], "connections": [ { "source": { "component": "mycylinder", "port": "port_b" }, "target": { "component": "mytee", "port": "port_in" } } ], "simulation": { "t_start": 0, "t_stop": 20, "step": 0.1, "method": "BDF" } } ``` ## draw.io XML 扩展约定 组件节点需要补充仿真语义: ```xml ... ``` 管段示例: ```xml ... ``` 孔板 / 阀门示例: ```xml ... ``` 连接需要从“组件级”升级到“端口级”: ```xml ``` 如果第一版来不及做端口选择,可以后端按组件类型和拓扑位置推断默认端口,但这只能作为 MVP 兜底。 ## 参数映射 从 draw.io / SystemModel 解析出的参数映射到 PythonModels 配置对象: ```text cylinder.volume -> CylinderConfig.volume cylinder.p0 -> CylinderConfig.p0 cylinder.T0 -> CylinderConfig.T0 tank.volume -> TankConfig.volume tank.p0 -> TankConfig.p0 tank.T0 -> TankConfig.T0 pipe.length -> PipeConfig.length pipe.diameter -> PipeConfig.diameter pipe.lambda_darcy -> PipeConfig.lambda_darcy pipe.p0 -> PipeConfig.p0 pipe.T0 -> PipeConfig.T0 orifice.K -> OrificeConfig.K orifice.opening -> OrificeConfig.opening ``` 注意:当前 `Orifice` 类支持 `opening`,但 `OrificeConfig` 暂时只有 `K`。建议后续给 `OrificeConfig` 增加 `opening` 字段,这样前端“阀门开度”才有实际落点。 ## 建议新增后端模块 ```text app/models/system.py app/services/drawio_parser.py app/services/model_validator.py app/services/pythonmodels_adapter.py app/services/simulation_runner.py ``` 职责: ```text app/models/system.py 定义 SystemModel、ComponentInstance、Connection、SimulationConfig。 app/services/drawio_parser.py 负责 draw.io XML -> SystemModel。 app/services/model_validator.py 检查组件、端口、参数、拓扑是否合法。 app/services/pythonmodels_adapter.py 负责 SystemModel -> TestModelConfig / TestModelRunConfig。 app/services/simulation_runner.py 调用 PythonModels,并把结果整理成前端可消费的 JSON。 ``` ## 建议新增接口 ```text POST /api/models/from-drawio 输入 draw.io XML 输出 SystemModel JSON POST /api/models/validate 输入 SystemModel 输出校验结果 POST /api/simulations/testmodel 输入 SystemModel + 仿真配置 输出仿真结果 POST /api/simulations/testmodel/from-drawio 输入 draw.io XML 一步完成解析、校验、仿真 ``` 第一版可以优先实现: ```text POST /api/simulations/testmodel/from-drawio ``` 这样页面点击“运行仿真”时可以直接把 draw.io XML 发给后端。 ## 第一版拓扑校验规则 第一版只支持固定 `TestModelSystem` 拓扑,因此校验可以严格一点: - 必须有 1 个 `cylinder`。 - 必须有 1 个 `tank`。 - 必须有 2 个 `tee`。 - 必须有 2 个 `orifice` 或 `valve`。 - 必须有 2 个 `pipe`。 - 连接必须形成两条支路。 - 每条支路必须是 `orifice -> pipe`。 - 上游必须从 `cylinder` 到第一个 `tee`。 - 下游必须汇入第二个 `tee` 再到 `tank`。 第一版不支持任意拓扑。 ## 实现步骤和进度 ### A. draw.io 侧建模增强 - [ ] 扩展组件库,增加 `cylinder / tee / orifice / pipe / tank`。 - [ ] 给每个组件写入 `modelType`、`role`、默认参数。 - [ ] 给组件补充端口语义。 - [ ] 给连接 edge 补充 `sourcePort / targetPort`。 - [ ] 前端增加“运行仿真”按钮。 ### B. SystemModel 数据层 - [ ] 新增 `app/models/system.py`。 - [ ] 定义 `SystemModel`。 - [ ] 定义 `ComponentInstance`。 - [ ] 定义端口级 `Connection`。 - [ ] 定义 `SimulationConfig`。 ### C. draw.io 解析 - [ ] 新增 `app/services/drawio_parser.py`。 - [ ] 支持 `mxGraphModel` 输入。 - [ ] 支持 `mxfile` 输入。 - [ ] 解析 `` 组件。 - [ ] 解析 `` 连接。 - [ ] 把 draw.io 参数转换成正确的 Python 类型。 - [ ] 输出标准 `SystemModel`。 ### D. 模型校验 - [ ] 新增 `app/services/model_validator.py`。 - [ ] 校验组件类型是否合法。 - [ ] 校验必填参数是否存在。 - [ ] 校验数值参数范围。 - [ ] 校验端口名是否合法。 - [ ] 校验连接 source / target 是否存在。 - [ ] 校验是否符合固定 TestModel 拓扑。 - [ ] 返回结构化错误列表。 ### E. PythonModels 适配层 - [ ] 新增 `app/services/pythonmodels_adapter.py`。 - [ ] 实现 `SystemModel -> CylinderConfig`。 - [ ] 实现 `SystemModel -> TankConfig`。 - [ ] 实现 `SystemModel -> PipeConfig`。 - [ ] 实现 `SystemModel -> OrificeConfig`。 - [ ] 实现 `SystemModel -> TestModelConfig`。 - [ ] 实现 `SimulationConfig -> SolveIVPConfig`。 - [ ] 如需要,给 `OrificeConfig` 增加 `opening` 字段。 ### F. 仿真运行 - [ ] 新增 `app/services/simulation_runner.py`。 - [ ] 调用 `PythonModels.scripts.run_testmodel.run_testmodel()`。 - [ ] 整理返回的 `series`。 - [ ] 返回 `mytank.p / mytank.T / mycylinder.p / mycylinder.T`。 - [ ] 返回 `branch..p / in / out`。 - [ ] 保留初始化诊断和求解诊断。 ### G. FastAPI 接口 - [ ] 新增 `POST /api/models/from-drawio`。 - [ ] 新增 `POST /api/models/validate`。 - [ ] 新增 `POST /api/simulations/testmodel`。 - [ ] 新增 `POST /api/simulations/testmodel/from-drawio`。 ### H. 前端结果展示 - [ ] 点击“运行仿真”后导出当前 draw.io XML。 - [ ] 调用 `/api/simulations/testmodel/from-drawio`。 - [ ] 展示校验错误。 - [ ] 展示仿真成功 / 失败状态。 - [ ] 展示结果表格。 - [ ] 展示压力、温度、流量曲线。 - [ ] 支持下载结果 JSON / CSV。 ## MVP 验收标准 第一版完成后,应能做到: - [ ] 打开 FastAPI 页面。 - [ ] 在 draw.io 画布中拖入气瓶、三通、阀门/孔板、管段、贮箱。 - [ ] 按固定 TestModel 拓扑连接组件。 - [ ] 配置主要参数。 - [ ] 点击运行仿真。 - [ ] 后端解析 draw.io XML。 - [ ] 后端生成 `SystemModel`。 - [ ] 后端映射到 `TestModelConfig`。 - [ ] 后端调用 `run_testmodel()`。 - [ ] 前端展示 `mytank.p`、`mytank.T`、`mycylinder.p`、`mycylinder.T`。 - [ ] 前端展示两条支路的压力和流量。 ## 后续阶段:通用拓扑仿真 固定 TestModel 跑通后,再考虑通用拓扑: ```text SystemModel -> instantiate components -> SimulationNetwork.add_component() -> SimulationNetwork.connect() -> 自动生成 rhs -> integrate_ode() ``` 这一步需要新增: - 通用 connector / stream 求解。 - 通用代数闭合。 - 任意 `Tee / Pipe / Orifice` 网络流量求解。 - 自动状态向量组装。 - 自动 `rhs` 生成。 当前不建议立刻做这一步,因为 `PythonModels/systems/testmodel_closure.py` 仍然是为 `TestModelSystem` 专门写的闭合器,不是任意拓扑求解器。 ## 当前优先级 下一步优先做: ```text draw.io XML -> SystemModel -> TestModelConfig -> run_testmodel() ``` 暂时不要直接做: ```text draw.io XML -> PythonModels 任意网络 ``` 这样最贴合现有代码,成本最低,技术债也最可控。