☰
SWMM一二维耦合模拟:从管网溢流到城市内涝淹没分析
2026/10/21 9:24:35 网站建设 项目流程

做SWMM深度二次开发的人,十有八九会卡在同一个问题上:一维管网模型算得再准,也没办法直接回答“低洼片区门口的积水到底淹到脚踝还是膝盖”。管网里的流量、流速、超载时长都能算得清清楚楚,但水一旦漫出检查井上了路面,走的就不再是管道,而是人行道、停车场、绿化带之间的地形通道,那一套一维圣维南方程就明显不够用了。这个系列写到专题13,我想集中把二维水动力模拟和耦合模拟这件事讲透:为什么必须耦合、耦合路线怎么选、网格怎么准备、数据怎么换、工程上又容易在哪里翻车。不管你是已经在看源码改造SWMM,还是正在评估自研内涝模型,这篇文章应该都能帮你省掉前面几轮试错。

1. 为什么一维管网模型装不下城市积水问题

1.1 城市淹水的物理事实:溢流不是“点”,而是“面”

管网模型里,检查井溢流通常被抽象成节点上的一个出流条件,井盖一旦被顶开,多余的水就记作溢流量。这个抽象在污水和雨水系统的日常运行评估里够用,但在内涝场景里会失真,因为真实的地面水流是沿着街道、地坪、建筑之间的通道铺开的。井盖顶开只是起点,后续的传播路径由地表高程、建筑物边界、道路边线共同决定。

二维水动力模拟要解决的就是这一段“地面流”的计算。地面漫流的速度通常很慢,但水深分布不均匀,一条路两侧可能相差几十厘米;低洼区域会先积水,道路交叉口会像容器一样把水蓄起来,然后在高水位下漫向相邻地块。这些现象没法用一维管道里的守恒方程表达,必须引入平面上的浅水方程和连续的地形网格。

1.2 SWMM原生求解器的能力边界

SWMM的管网求解核心是有限体积格式的一维圣维南方程,再加上节点水位-体积关系来衔接不同管段。节点积水(ponded area)逻辑可以记录超载水量,但它本质上是零维的蓄水计算:给定一个积水面积和深度关系,算一个水位,水并不会向相邻节点流动。换句话说,它能告诉你哪些井溢流了、溢了多少,但没法告诉你这些水会往哪个方向流、会在哪些低洼位置停留。

这就是一维模型和二维模型之间的能力断层。SWMM算出的溢流总量可以作为二维模型的入流边界,但“二维地面的水位反过来会不会顶托管网排水、雨水口会不会返涌”这类问题,单靠SWMM解不出来。要回答回水顶托和倒灌问题,必须做双向耦合。

1.3 什么时候值得上二维耦合

我见过不少团队一上来就追求全二维化,结果网格划得很细、机器跑不动、数据也凑不齐,最后模型成了摆设。二维耦合不是所有项目都需要的。判断标准其实很朴素:如果业务决策只关心管网负荷、溢流体积、泵站运行时间,一维模型足够;如果业务决策要出淹水图、要评估小区淹没深度、要划分风险等级,那就必须有二维部分。

任务类型推荐方案原因
管道能力评估、溢流总量统计一维SWMM精度够用,成本低
河道水位顶托、管网倒灌分析一维河道+管网耦合重点是纵向高程关系
城市内涝淹没图、地块风险评估一维管网+二维地面耦合需要地面水深和漫流路径
实时预警、调度预案耦合模型+简化代理需要时效性,模型需降阶

换句话说,二维耦合是给“地面响应”补课,不是要把SWMM替换掉。两者的关系是:管网负责地下的有压和无压输水,二维模块负责地上的积水扩散和汇流,耦合点就是那些井盖、雨水口和排水出口。

2. 二维耦合的三种主流路线:松散、紧密和折中方案

2.1 松散耦合:把溢出当单向边界

松散耦合是最容易实现的方式:先用SWMM单独跑一遍,把溢流节点的流量过程线记录下来,再把这个流量作为二维模型的入流边界;二维模型的地面水位,又作为管网出口的固定下游水位回传。整个过程可以分成两次独立运算,开发量很小,适合快速评估。

它的局限也很明显:节点和地面单元之间的水头差没有实时反馈。如果某个检查井溢流后地面水位很快涨高,势必会减弱后续溢流速率;松散耦合忽略了这个反馈,容易高估溢流总量。反过来,当管网满管但地面水位比井底高程还高时,回水顶托效应也没有被表达,管网会继续按原来的能力排水,结果偏乐观。

2.2 紧耦合:每个时间步双向交换流量和水位

我们在实际二次开发中用的是另一种路线:把SWMM的节点和二维地面网格定义为共享边界,在每个时间步里根据相对水头计算交换流量。简单说,就是两类判断:

  • 节点水位高于相邻单元格水位:水从管网溢向地面,交换流量按堰流或孔口公式计算;
  • 单元格水位高于节点水位:水从地面返灌进管网,交换流量方向取反。

这个模式可以天然表达雨水口返涌、检查井顶托、管网倒灌等物理过程。难点在于求解器的步长不一致。SWMM的内部求解用了隐式格式,完整跑一个5秒甚至30秒的时间步问题不大;而二维浅水方程如果用显式有限体积格式求解,受CFL条件限制,时间步长往往只有0.1到2秒,边长越小、水深越大,步长越小。

所以紧耦合的主循环通常不是“两套模型同步走一步”,而是SWMM走一个大步,二维模块在这个大步内拆成若干子步,每个子步都把边界流量更新一次。

2.3 耦合模式选型该看什么

开发之前先列清楚选型指标,不然中途换路线很痛苦。我自己一般看四项:一是质量误差,能不能在一个完整的降雨过程中把水量平衡误差控制在1%以内;二是稳定性,连续降雨十几个小时不出现非物理振荡;三是扩展性,以后要加二维入渗、降雨损失、泵闸调度时,边界条件好不好改;四是维护成本,SWMM版本升级后,耦合层的代码要改多少。

在多数城市内涝项目中,紧耦合是综合收益最高的,哪怕初期开发量稍大也值得。如果只是给某个片区做定性分析,时间又紧,松散耦合可以快速出图,但要在报告里写清适用边界,别让决策者把单向耦合结果当成精确淹没信息。

3. 网格与地形:二维模型不是画个矩形就能跑

3.1 从DEM到计算网格:先做地形“体检”

二维水动力模拟的网格可以从DEM直接生成,但DEM拿来就用的坑很多。第一是建筑物,DEM里的建筑顶面高程往往和屋顶一致,如果直接作为地形参与计算,水会“流进”建筑内部;需要把建筑物切掉或抬高成不透水障碍单元。第二是立交桥、高架路、地下通道入口这类特殊地形,它们对水流的拦挡和通道作用完全相反,必须在网格生成阶段单独处理。

推荐的工作流是:先对DEM做清洗,把桥、隧、建筑轮廓叠加到地形数据上;再根据道路边线和水流主干方向生成三角形或四边形网格;最后在低洼点和耦合节点附近做局部加密。起步阶段别把网格划得太细,一个测试片区先用5米到10米的单元尺寸跑通流程,再决定是否细化到2米或3米。

3.2 把管网节点挂到二维网格上

紧耦合里特别关键的一步是建立“节点-单元”映射关系。管网节点有坐标,二维网格有单元中心坐标,常规做法是把节点坐标落到所处的单元内,再把该单元标记为耦合单元。但一个节点只对应一个单元会有问题:当节点所在单元面积特别小或特别大时,源项注入和回流都会失真。

实际工程里我通常采用权重分配:以节点为中心,找出周围三到五个单元,根据地形低洼趋势和单元面积分配交换流量权重。权重之和必须为1,且每次耦合计算时保持同一套权重。这套权重可以事先算好存下来,运行时不重复计算,能省不少时间。

3.3 网格细化是双刃剑:更细不等于更快

二维模型的计算成本受网格尺寸影响很大,而且不是线性增长。显式求解器的时间步长由CFL条件限制,大致满足以下关系:

[ \Delta t \leq \alpha \frac{\Delta x}{\sqrt{gh}} ]

(\Delta x) 是单元边长,(h) 是水深,(\alpha) 是安全系数。网格边长缩小一半,空间单元数可能变成四倍,时间步长也要跟着降低,总计算量可能膨胀十几倍。所以网格细化必须克制,只加密道路、低洼地带、耦合点周边;大范围的绿地和平坦区域用粗网格即可。

我在测试地块上做过对比:全局5米网格比10米网格慢约7倍,但最大淹没范围只差了不到5%;而在低洼片区做局部2米加密后,关键点位的峰值水深提升了约12%,这部分误差才真正影响风险等级判断。网格策略要和业务精度需求绑定,而不是盲目追求“看起来精细”。

4. 耦合求解器中的数据交换与水量守恒

4.1 该交换水位还是交换流量

耦合边界的数据类型是个容易被忽略的技术决策。只交换流量,实现简单,但节点和单元之间缺少水头反馈,管网溢流会被高估。完整紧耦合应该同时交换水位和流量,通过相对水头驱动交换过程。

工程上常用的交换公式类似这样:当地面水位低于节点水位时,按宽顶堰公式计算溢流;当地面水位高于节点水位时,按孔口淹没出流公式计算回流。两个公式的衔接处要平滑过渡,否则水位刚好接近井口高程时,流量会突然跳变,产生振荡。

# 耦合点交换通量的简化示意 if h_node > h_cell + z_offset: q_exchange = Cw * width * (h_node - h_cell) ** 1.5 # 溢流 elif h_cell > h_node: q_exchange = -Cd * area * sqrt(2 * g * (h_cell - h_node)) # 返灌 else: q_exchange = 0.0

这里的 (h_node) 是节点水位,(h_cell) 是相邻网格水位,(z_offset) 是井口或雨水口高出地面的附加高差。流量系数 (Cw)、(Cd) 需要根据局部实际情况标定,默认值不能直接抄手册。

4.2 大小时间步下的质量守恒怎么做

SWMM隐式求解可以走大步,二维显式求解必须走小步,耦合后最大的麻烦就是质量守恒。做法是把一个管网时间步内的交换总量切成二维子步逐段结算,保证二维侧每个子步看到的是最新边界条件。

还可以在内存里维护一张“水量平衡表”:每个节点记录当前管网对地面的累计溢流量、地面返灌量、初始积水量、当前积水量。每一个管网大步结束后,即使二维还没有跑完,水量平衡表也应该能对上账。如果差量超过0.5%,就先别继续往后跑,回头查是边界流量重复计算还是权重分配没归一化。

4.3 收敛判断与边界振荡

耦合边界最典型的问题是“锯齿振荡”:交换流量在相邻两个时间步里正负交替,水位也在节点和单元之间来回跳。这通常不是求解器不稳定,而是边界条件切换太刚硬。

解决办法有三个。第一,引入松弛系数,让交换流量慢慢逼近目标值;第二,把堰流和孔口公式之间的切换带设置成一段过渡区间,而不是一个临界点;第三,限制单时间步内的交换水量不超过网格允许的容积变化量,防止一个步长灌太多水导致水面剧烈起伏。

我自己常用松弛系数0.3到0.5。数值振荡严重时优先查网格尺寸和水位差跨度,不要一上来就压缩全局时间步长,那样只会让计算更慢而问题依旧。

5. 实操案例:某片区管网模型扩成1D-2D耦合模型

5.1 数据准备与前期检查

我用一个虚构造型的试点片区来说明流程。片区面积约2平方公里,管网数据来自市政竣工图,维护得还可以,但检查井坐标和井底高程有几个明显错误。这一步不能跳过,否则后面耦合时,流量从错误高程的井里溢出,结果没法解释。

地形数据用的是某测绘单位提供的0.5米分辨率DEM,但建筑轮廓数据没带屋顶高程,需要重新处理。做法是把建筑边界多边形叠加到DEM上,把建筑内部单元高程抬高到一个不透水高度,模拟建筑对地表漫流的阻挡效果。

然后划分网格:整个片区先用10米三角形网格铺底,道路、低洼区、两端耦合井附近加密到2米。初始网格量约8万个单元,跑一次短历时降雨测试大约需要40分钟;验证逻辑通了之后再考虑细化。

5.2 耦合主循环的骨架代码

二次开发的主循环可以参考下面这段伪代码。核心思路是:SWMM每走完一个管网时间步,取出耦合节点的水位和溢流量;二维模块根据这些边界值连续跑若干子步;当二维累计水量达到管网站对应水位对应的容积变化时,更新节点水位,再进入下一轮。

# 耦合主循环示意(伪代码) while not swmm_end(model): # 1D 管网步进 swmm_step(model, dt_1d) for node in coupling_nodes: h_node = get_node_depth(node) q_1d = get_node_overflow(node) # 2D 子步推进 for sub_step in range(n_steps_2d): h_cell = get_cell_depth(cell_of_node[node]) q_ex = exchange_flux(h_node, h_cell, node) apply_flux_to_mesh(q_ex, weights[node]) advance_2d(dt_2d) # 更新 SWMM 节点水位 set_node_stage(node, get_cell_depth(cell_of_node[node])) # 输出和水量平衡检查 if step % check_interval == 0: check_water_balance()

真实开发中要考虑更多细节,比如二维模块的高程基准和管网井口高程是否统一、坐标系统是否是同一套投影、耦合点附近是否设置了最小水深阈值。这些看似无关紧要的约定,往往决定模型能不能收敛。

5.3 参数、后处理与验证

耦合模型的参数可以分为三类:管网侧参数、二维侧参数、交换侧参数。管网侧沿用SWMM原有率定结果;二维侧主要是曼宁糙率,地面糙率一般在0.01到0.05之间,裸土、道路、草地差异明显;交换侧需要标定的就是堰流系数和孔口系数。

参数初值调参方向
二维地面糙率0.03峰值水深偏高则增大,偏低则减小
耦合点堰流系数0.6溢流范围偏大则减小
耦合点孔口系数0.5返灌偏慢则增大
干湿边界阈值0.001米太小易闪振,太大易丢水量

验证阶段我习惯看三张图:最大淹没深度图、峰值时刻水面线、耦合点交换流量过程线。最理想的情况是拿历史淹水照片或积水深度给定位来校核,没有实测数据时,至少要把网点溢流总量和二维积水总量加在一起,拿去和降雨量做闭合校验。闭合误差能稳定在1%以内,这个模型才敢往外拿。

6. 二次开发中常见的坑与性能优化

6.1 双向耦合回流发散:问题常出在“出口口径”

回流发散是紧耦合最容易遇到的坑。管网节点和地面单元之间的水位差不大时,交换方向很容易来回跳动,表现为流量时序上的锯齿波。更隐蔽的是,同一个耦合点连接了多个单元,如果单元之间水位差较大,同一个节点可能同时出现“部分单元回流、部分单元出流”的尴尬局面。

处理办法是把耦合点边界统一水位取加权平均,再统一判定方向。不要允许同一个耦合点在同一个时间步内既出流又回流,那在物理上是不合理的。口径尺寸也要从几何上量准确,雨水口、检查井口直径直接影响孔口出流面积,差一倍流量就差几倍。

6.2 干床和负水深的处理

二维浅水方程数值格式遇到底坡项处理不好时,干湿过渡区域很容易出现负水深。这个问题的本质是:水面梯度很小、单步排水量超过当前单元格的积水量,于是水被“排没了”还继续扣。

工程上通用的做法是设一个干湿阈值。水位低于阈值时,该单元退出水力计算,只保留水深状态;水位重新超过阈值后才唤醒。赋值时要保证阈值和网格尺寸匹配,太大会把浅水区域当成干底,造成水量损失;太小会频繁切换,拖慢计算。

6.3 性能优化:把计算资源留给真正的瓶颈

网格数量和计算时长是耦合模型最直接的矛盾。显式二维求解非常适合并行化,可以按空间分区、每个线程负责一块网格,分区只交换边界单元的水深和流速。这种并行方式对数据结构的连续性很挑剔,节点数组尽量用紧凑的顺序存储,避免在循环里频繁做动态分配。

另一个容易见效的点是自适当地时间步长。根据当前最大水深和流速估算局部CFL数,在安全范围内动态调整步长,浅水缓流阶段用大步,深水急流阶段用短步。相比固定小步长的做法,同一场降雨能把运行时间缩短30%到50%,而计算结果几乎不变。

最后再分享一个我反复用的小技巧:耦合模型跑完之后别只盯最大淹没图,把每个耦合节点的交换流量时序拉出来看一眼。凡是出现锯齿形正负交替的节点,基本都是边界处理或流量系数没到位,先把地形高程和井口相对关系核对一遍,往往比盲目缩网格更有效。这个习惯虽然不起眼,但在验收阶段帮我少返工了不知道多少次。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询