SystemSimulationApp
SystemSimulationApp 是一个面向系统仿真的可视化建模原型。当前项目已经具备两条基础能力:
- 使用 FastAPI 嵌入 draw.io,提供可视化拖拽建模界面。
- 使用
PythonModels中已有的 Python 仿真模型,运行当前固定拓扑的TestModelSystem。
下一阶段的目标是把这两条能力接起来,先完成一个小 MVP:
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 仿真骨架:
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 支持的是固定拓扑:
mycylinder
-> mytee
-> myorifice -> mypipe
-> myorifice1 -> mypipe1
-> mytee1
-> mytank
因此第一版不要做任意拓扑仿真,而是先把 draw.io 中画出的这个固定拓扑映射到现有 TestModelSystem。
核心原则
不要让仿真逻辑直接依赖 draw.io XML。
推荐分层:
draw.io XML
-> SystemModel
-> PythonModels adapter
-> PythonModels runner
-> SimulationResult
其中:
- draw.io XML 只是可视化画布格式。
SystemModel是系统仿真的核心结构化数据。- PythonModels adapter 负责把
SystemModel转成TestModelConfig / TestModelRunConfig。 - 仿真器只认结构化模型,不直接解析画布。
这样后续即使替换 draw.io,仿真层也不用推倒重来。
MVP 范围
第一版只支持当前 TestModelSystem 对应的拓扑:
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 |
前端可以继续显示“阀门”,但底层建议使用:
modelType="orifice"
因为 PythonModels 里实际对应的是 Orifice。
SystemModel 设计
建议新增统一结构:
{
"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 扩展约定
组件节点需要补充仿真语义:
<object
id="mycylinder"
label="气瓶"
componentType="cylinder"
modelType="cylinder"
role="cylinder"
volume="0.01"
p0="35000000"
T0="300">
...
</object>
管段示例:
<object
id="mypipe"
label="上支路管段"
componentType="pipe"
modelType="pipe"
role="upper_branch.pipe"
length="5.0"
diameter="0.02"
lambda_darcy="0.02"
p0="100000"
T0="300">
...
</object>
孔板 / 阀门示例:
<object
id="myorifice"
label="上支路孔板"
componentType="valve"
modelType="orifice"
role="upper_branch.orifice"
K="0.00001"
opening="1.0">
...
</object>
连接需要从“组件级”升级到“端口级”:
<object
id="edge1"
sourcePort="port_b"
targetPort="port_in">
<mxCell edge="1" source="mycylinder" target="mytee" />
</object>
如果第一版来不及做端口选择,可以后端按组件类型和拓扑位置推断默认端口,但这只能作为 MVP 兜底。
参数映射
从 draw.io / SystemModel 解析出的参数映射到 PythonModels 配置对象:
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 字段,这样前端“阀门开度”才有实际落点。
建议新增后端模块
app/models/system.py
app/services/drawio_parser.py
app/services/model_validator.py
app/services/pythonmodels_adapter.py
app/services/simulation_runner.py
职责:
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。
建议新增接口
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
一步完成解析、校验、仿真
第一版可以优先实现:
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输入。 - 解析
<object>组件。 - 解析
<mxCell edge="1">连接。 - 把 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.<name>.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 跑通后,再考虑通用拓扑:
SystemModel
-> instantiate components
-> SimulationNetwork.add_component()
-> SimulationNetwork.connect()
-> 自动生成 rhs
-> integrate_ode()
这一步需要新增:
- 通用 connector / stream 求解。
- 通用代数闭合。
- 任意
Tee / Pipe / Orifice网络流量求解。 - 自动状态向量组装。
- 自动
rhs生成。
当前不建议立刻做这一步,因为 PythonModels/systems/testmodel_closure.py 仍然是为 TestModelSystem 专门写的闭合器,不是任意拓扑求解器。
当前优先级
下一步优先做:
draw.io XML
-> SystemModel
-> TestModelConfig
-> run_testmodel()
暂时不要直接做:
draw.io XML
-> PythonModels 任意网络
这样最贴合现有代码,成本最低,技术债也最可控。