模块 8a · Channel routing 的网络实现(cell-to-cell)

模块7 的 KW 是集总单河段;真实的 channel routing 是网络:每格自己解 KW,把出流交给唯一下游格(D8),按"上游先算"的拓扑序扫一遍。本页在 Y 形河网上让你看见水波走、看见支流叠加

EF5 网络机制(源码锚定)

1. 处理顺序 = 按 flow accumulation 升序 (BasicGrids.cpp:233 gridCells.sort) -> 上游格先算,同一时间步内水沿网络级联到下游 2. 每格解完 KW 后推送到唯一下游格 (KinematicRoute.cpp:238-241) kwNodes[downStreamNode].incomingWater += newq (D8 单流向) 3. 河道 vs 坡面: flow_accum > TH 判为河道格 (KinematicRoute.cpp:473) 坡面用 ALPHA0、河道用 ALPHA(曼宁 n 藏在里面, 见模块7) 4. 面积换算: leak x node->area / downstream->area (LinearRoute.cpp:104)

我们的教学网络:全部当河道格、单位格距、一个 alpha——机制不变、去掉工程细节。lab 里 blocks/network.py 与此页代码一致。

交互实验台:Y 形河网(长支流 A + 短支流 B → 主干 C)

同一场 10mm 雨落在四个不同位置,出口听到的"回声"完全不同——距离=延迟+衰减。改代码或拖参数重跑。

河网拓扑(红三角=出口;编号=处理顺序,构造序即拓扑序)
同一场 10mm 雨、四个位置的出口响应——峰时/峰值都标在图例里
看见水波走:源头 20mm 脉冲后,沿 A→出口路径的流量剖面快照(波推进 + 衰减)

CREST 的 routing 完全解剖:lr vs kw

先厘清一件事:EF5 里 CRESTModel.cpp 只管产流,routing 是独立插件,配置文件里 route=lrroute=kw 二选一(也可配 sac+kw 等)。所以"CREST 的 routing"有两个答案:

lr = LinearRoute(Wang 2011 原生 CREST 汇流)kw = KinematicRoute(FLASH 业务标配)
快流机制水库漏出 leak=S×LEAKO(:82) + travel-time 投递逐格运动波隐式方程 + Newton 迭代(:210-230)
延迟来自速度nexTime=格长/速度,速度=depth^0.66·√S·(RIVER|COEM)(:244)蓄量:隐式项 αQ^β 即每格非线性蓄量
投递方式沿下游累加 nexTime 直到用完一步,把水线性插值分给落点前后两格(:279-310) —— 可跨多格解完推给唯一下游格(:238)
主旋钮LEAKO / LEAKI / COEM / RIVER / TH / UNDERALPHA(河道) / ALPHA0(坡面) / β=0.6硬编码 / LEAKI / UNDER / TH
慢流(interflow)两者完全相同:IR 水库 leak=S×LEAKI + speedUnder=UNDER×√slope 的 travel-time 投递(kw:245-253,:492 与 lr 同构)→ 换 route 只换了快流物理
求解方式直接计算(无迭代):算速度 → 走 → 投递迭代求解:每格每步 Newton 解隐式方程
实测成本
(本课 Python 实现)
13/121/241 格:19 / 65 / 60 ms
平均只走 1.06 格(跨多格是能力、非常态)
19 / 92 / 123 ms → 241 格时慢 2.0×
Newton 平均 1.13 次收敛(上限10次几乎不触发)
河道格特殊处理河道格快流直通不入库(:89-91)河道格解两次:坡面(ALPHA0,状态PO) + 河道(ALPHA,状态PQ)(:285,:338)

成本说明(诚实):2× 差距部分是实现差异——lr 把最贵的速度计算向量化了,kw 的 Newton 是逐格标量循环(含 pow)。EF5 的 C++/OpenMP 下常数因子不同,但结构性差异成立:kw 每格每步迭代求解,lr 直接算。另:Newton 平均 1.13 次就收敛,因为上一步的 Q 是极好的初值——"10 次迭代"是安全网不是常态。

三个源码级发现
"Coupled" 已成历史名:Wang 2011 的产流↔汇流反馈(汇流水回灌下游格)在 EF5 中被注释掉了(CRESTModel.cpp:137-140, :152-153, :237-238)。
"LinearRoute" 其实非线性:速度每步按水深重算 → 传播时间随流量剧变。实测同一河网源头脉冲:1mm 峰现 t=59、20mm 峰现 t=19、200mm 峰现 t=10。名字只是说"蓄量-出流"是线性的。
kw 是混合体:只有 overland/channel 用运动波,interflow 仍是水库+travel-time(同 lr)。
④ 两者都因拓扑序扫描(flow-accum 排序)能在同一步内跨越全网——差别不在"能跳几格",而在"延迟由速度还是蓄量决定"。

并排跑:同一河网、同一脉冲,两套 routing

蓝=lr(原生 CREST:水库+travel-time 投递) · 红=kw(运动波) · 拖脉冲大小看两者的非线性各自如何表现

时空图:看见水在哪(routing 最重要的一张图)

过程线只告诉你"出口什么时候有水"。要理解 routing,得看水在空间上随时间怎么移动: 横轴时间、纵轴河道位置、颜色 = 该格的水量。洪水波会显示成一条斜纹—— 斜纹的斜率就是波速。拖动脉冲大小,看斜纹变陡(变快):这就是非线性的可视化。

14 格直河道,t=2 时在最上游给一个脉冲。白线 = 每格洪峰到达时刻(波脊)。颜色为对数刻度的"占脉冲比例",三种脉冲可比。

逐步追踪:3 格算例的每一个中间量

最小可手算算例:3 格链 0→1→2→出口,t=0 时给 cell0 灌 10mm。 下面把每一步的每一个中间量都打印出来——蓄量、漏出、水深、速度、nexTime、下游行走过程、插值权重、投递去向(lr); 以及 rhs 组装与每一次 Newton 迭代(kw)。


    

术语 Glossary

拓扑序 · Topological / flow-accumulation order
Process cells so every cell is solved AFTER all its upstream cells. EF5 gets this by sorting on flow accumulation (BasicGrids.cpp:233). Within one time step, water cascades through the whole network in a single sweep.
保证每格在其全部上游算完之后再算。EF5 用 flow accumulation 升序实现;一次扫描内水就能沿全网级联到下游。这是分布式汇流的调度核心。
汇合叠加 · Confluence superposition
The outlet hydrograph is the sum of tributary contributions, each delayed by its travel time. Different tributary lengths create multi-peaked or broadened responses — basin SHAPE writes itself into the hydrograph.
出口过程线=各支流贡献按各自传播时间延迟后的叠加。支流长短不同→复峰或展宽——流域形状会写进过程线里
传播时间 · Travel time / 距离-衰减
Each cell adds delay and attenuation; a pulse near the outlet arrives sharp and early, a headwater pulse late and damped. Quantified in the legend (peak time/height).
每过一格=多一份延迟+衰减:近出口的雨又早又尖,源头的雨又晚又平。图例里的峰时/峰值就是量化。
lr 的 travel-time 投递 · Travel-time delivery(CREST 原生汇流核心)
Per step: compute each cell's crossing time nexTime = length/speed (speed from Manning-style depth^0.66*sqrt(slope)*roughness multiplier). Walk downstream accumulating nexTime until one time step is spent; deliver the leaked water to the two cells straddling that point with linear interpolation weights (LinearRoute.cpp:279-310). Water can cross MANY cells per step; travel time is recomputed from depth every step, so celerity is flow-dependent.
每步:算每格的过境时间 nexTime=格长/速度(速度用曼宁式 depth^0.66·√坡度·糙率倍数)。沿下游累加 nexTime 直到耗尽一个时间步,把漏出的水按线性插值权重分给落点前后两格(cpp:279-310)。水一步可跨多格;速度每步按水深重算 → 波速随流量变化(所以"Linear"Route 其实非线性)。
LEAKO / COEM / RIVER / UNDER(lr 参数组)
LEAKO/LEAKI: per-step leak fractions of the overland/interflow reservoirs. COEM/RIVER: Manning roughness multipliers for hillslope vs channel cells (channel faster). UNDER: interflow speed multiplier (speedUnder=UNDER*sqrt(slope)). TH: flow-accumulation threshold separating channel from hillslope.
LEAKO/LEAKI=坡面/壤中水库每步漏出比例;COEM/RIVER=坡面/河道的曼宁糙率倍数(河道更快);UNDER=壤中流速度倍数;TH=区分河道与坡面的汇流面积阈值。曼宁 n 就藏在 COEM/RIVER 里(模块7)。
河道判据 TH · Channel threshold
Cells with flow accumulation above TH are channel cells (KinematicRoute.cpp:473): channel alpha vs hillslope ALPHA0 — because overland Manning n is ~10x channel n (Module 7).
汇流面积超过 TH 的格判为河道(cpp:473);河道/坡面分用 ALPHA/ALPHA0——因为坡面有效曼宁 n 比河道大一个量级(模块7)。
anchor: EF5 BasicGrids.cpp:233 (ordering) · KinematicRoute.cpp:238 (downstream push), :473 (TH) · lab: blocks/network.py