尧图精选

一维河道水动力学建模:圣维南方程组与Preissmann隐式差分求解

🕒 发布时间:2026/10/2 9:47:02 📁 来源:尧图网络
简介面向水利工程、水文分析领域的科研人员与相关专业学生这是一套基于MATLAB的一维河道水动力学建模实现方案。核心围绕圣维南方程组求解采用Preissmann离散法处理偏微分方程结合上下游边界条件在简化纵向流动的前提下模拟河道水位与流量变化适用于洪水预警、水资源管理及水利工程设计。资源包共5个文件涵盖1个m格式核心主程序、1个mat格式数据文件及3个txt文本资料整体仅401KB其中主程序负责圣维南方程组的离散求解数据文件存储河道断面、初始与边界条件文本资料则提供澄通河段地形参数和建模使用说明。目前已有59人学习浏览研读后可掌握一维圣维南方程组从离散化到代数求解的完整MATLAB思路替换输入参数即可开展不同河道场景的模拟适合具备流体力学基础、希望快速上手数值建模的读者。1. 一维河道水动力学建模从圣维南方程组到一条能用的水位过程线做防洪评价、水库调度或者参加华为杯这类建模竞赛的人大概率都经历过这种时刻手里有河道大断面测量数据有上下游水文站的流量水位过程线想算一场洪水演进之后沿程各断面的水位结果不是 HEC-RAS 装不上就是被图形界面上几十个参数劝退。这个 zip 包我拆完之后的第一印象是它把一维河道水动力学建模这件事收得很干净圣维南方程组、Preissmann 隐式差分、追赶法求解器、断面与边界条件数据模板、率定脚本都在里面解压后先跑通自带算例再把数据换成你自己的断面就能出结果。适合设计院做防洪评价的工程师、算纳污能力的水环境从业者以及需要在比赛里快速给出水位—流量过程线的建模队伍。它不是黑匣子核心求解代码都是可见可改的几十公里的河道算一场完整洪水普通笔记本也能在可接受的时间内跑完。2. 模型原理与离散格式为什么是 Preissmann 隐式差分而不是显式2.1 控制方程连续方程与动量方程各自负责什么一维明渠非恒定流的控制方程是圣维南方程组由连续方程和动量方程组成。连续方程描述质量守恒∂A/∂t ∂Q/∂x q其中 A 为过水断面面积Q 为断面流量q 为旁侧入流单位长度侧向汇入或流出。动量方程描述动量守恒常见写法是∂Q/∂t ∂(Q²/A)/∂x gA(∂Z/∂x S_f - S₀) 0这里 Q²/A 这一项是对流项gA∂Z/∂x 是压力项S_f 是摩阻坡S₀ 是河底底坡g 为重力加速度。这个方程里用 Z水位而不是水深 h 作为因变量是刻意为天然河道准备的天然断面形态不规则水深和水位之间的关系不容易写成简单的函数而水位 Z 可以直接对应到实测的大断面数据。摩阻坡 S_f 用曼宁公式计算S_f n²Q|Q| / (A²R^(4/3))其中 n 是曼宁糙率系数R 是水力半径对于宽浅河道通常近似取水深或面积除以湿周。注意这里 Q 外面加了绝对值这是为了保证倒流时摩阻方向正确——很多初学的人在这里踩坑流量为负时如果不加绝对值摩阻项方向反了模型会给出完全错误的水位结果。这个包里的求解器在代码层面是严格按这个形式实现的属于“看着简单但细节到位”的那类实现。2.2 Preissmann 四点隐式格式θ 权重怎么选对这类双曲型偏微分方程组显式格式在天然河道里几乎没法用。原因很直接显式格式受 Courant 条件约束一场洪水过程往往要算几千上万步而实际调度或防洪评价需要的是 1 小时、甚至 30 分钟一个输出断面数据计算效率必须在线。所以这个资源采用的是 Preissmann 四点隐式格式这是工程领域处理一维河道非恒定流事实上的标准格式。Preissmann 格式的核心思想是在每个计算网格相邻两个断面之间上把变量在空间和时间两个方向上做加权平均。对任意变量 f定义f ≈ (θ/2)(f_i^(n1) f_(i1)^(n1)) ((1-θ)/2)(f_i^n f_(i1)^n)时间导数近似为∂f/∂t ≈ (f_i^(n1) f_(i1)^(n1) - f_i^n - f_(i1)^n) / (2Δt)空间导数近似为∂f/∂x ≈ θ(f_(i1)^(n1) - f_i^(n1))/Δx (1-θ)(f_(i1)^n - f_i^n)/Δx这里的 θ 是时间权重取值在 0.5 到 1.0 之间。θ 0.5 时格式对时间具有二阶精度但工程实践中反而容易在陡坡段产生锯齿状振荡θ 1.0 时是全隐式最稳但时间精度掉到一阶。资源里默认给的是 0.65这是一个很典型的工程折中值。提示所谓“无条件稳定”是线性化意义下的结论。对真实河道这种强非线性问题θ 取 0.5 照样可能在涨水段激起振荡遇到这种情况优先把 θ 往上调而不是去调小时间步长这是教科书不会告诉你的操作习惯。2.3 离散残差与追赶法核心代码长什么样把连续方程和动量方程在相邻断面 i 和 i1 之间离散后每个网格产生两个残差方程目标是求水位和流量在所有断面上的值。残差函数是求解器的核心这个包里的实现大致长这样import numpy as np def swe_residual(A, Q, Z, A_old, Q_old, Z_old, river, dt, dx, theta): 计算圣维南方程组在 Preissmann 格式下的残差 A/Q/Z: 当前迭代步各断面的面积、流量、水位 A_old/Q_old/Z_old: 上一时间步的值 river: 断面几何对象提供 area_from_z、湿周等接口 n_interval river.n_intervals res np.zeros(2 * n_interval) for i in range(n_interval): # 连续方程残差: dA/dt dQ/dx - q 0 dA_dt (A[i1] - A_old[i1] A[i] - A_old[i]) / (2.0 * dt) dQ_dx theta * (Q[i1] - Q[i]) / dx (1.0 - theta) * (Q_old[i1] - Q_old[i]) / dx res[2*i] dA_dt dQ_dx - river.side_inflow[i] # 动量方程残差: dQ/dt d(Q^2/A)/dx g*A*dZ/dx g*A*(Sf - S0) 0 dQ_dt (Q[i1] - Q_old[i1] Q[i] - Q_old[i]) / (2.0 * dt) conv_flux Q[i1]**2 / max(A[i1], 1e-6) - Q[i]**2 / max(A[i], 1e-6) conv_dx theta * conv_flux / dx (1.0 - theta) * ( Q_old[i1]**2 / max(A_old[i1], 1e-6) - Q_old[i]**2 / max(A_old[i], 1e-6) ) / dx dZ_dx theta * (Z[i1] - Z[i]) / dx (1.0 - theta) * (Z_old[i1] - Z_old[i]) / dx # 摩阻坡取相邻断面的平均值 A_mean 0.5 * (A[i] A[i1]) Q_mean 0.5 * (Q[i] Q[i1]) R_mean 0.5 * (river.hydraulic_radius(i, Z[i]) river.hydraulic_radius(i1, Z[i1])) Sf river.n_manning[i]**2 * Q_mean * abs(Q_mean) / (A_mean**2 * R_mean**(4.0/3.0)) res[2*i1] dQ_dt conv_dx 9.81 * A_mean * dZ_dx 9.81 * A_mean * (Sf - river.slope[i]) return res这段代码里的关键参数含义theta是时间权重dt和dx分别是时间步长和断面间距river.side_inflow[i]是第 i 个网格的旁侧入流river.slope[i]是河底坡降。Q**2 / A这一项在 A 接近 0 时会出现除以零的问题所以加了max(A, 1e-6)做保护这是干河床启动时防止 NaN 的第一道防线。Sf的计算里用了相邻断面摩阻坡的平均值比用单点值更稳因为摩阻坡对水深非常敏感单点取值容易在断面变化剧烈处造成残差振荡。残差算出来之后整个问题变成一个大型稀疏方程组。本资源采用追赶法Thomas 算法求解三对角系统在每次迭代中对非线性项做一阶泰勒展开形成雅可比矩阵。追赶法的好处是不需要显式存储大矩阵内存占用小几十个断面的河道秒级就能完成一次迭代。关于具体的矩阵组装方式第 4 章会展开讲。3. 输入数据怎么喂给模型断面表格、边界条件与糙率文件组织3.1 断面数据文件从测量成果表到水位-面积-湿周表拿到实测的大断面测量成果表后最痛苦的一步不是建模而是数据整理。测量成果表通常是一串起点距和对应高程的点对比如“0m 处高程 102.5m5m 处高程 101.8m……”模型需要的不是这个而是“水位—过水面积—湿周”的对应关系。这个转换必须你自己做资源里提供了转换脚本和模板文件。资源里的断面文件是 CSV 格式每一行对应一个断面关键列定义如下列名含义示例mileage断面距河道起点的里程单位 m1250.0elev水位高程单位 m98.5area该水位下的过水断面面积单位 m²342.7wetted_perimeter该水位下的湿周单位 m86.3一个断面在 CSV 里占多行每一行是一个水位节点所有行按水位从低到高排列。两个相邻断面之间模型内部做线性插值所以断面文件里不需要额外加密断面。这里有一个新手常犯的错误把测量成果表的“测点高程”当成“水位高程”直接填进 elev 列。正确做法是先确定你要模拟的水位范围从河底最低高程开始到最高设计洪水位加一点富余然后针对每个水位用起点距-高程点对去积分算出面积和湿周。这个转换用 Python 写很简单核心逻辑是根据水位线与断面点对求交然后累加梯形面积import numpy as np from scipy.interpolate import interp1d def section_to_table(distance, elevation, z_min, z_max, dz0.1): 把实测大断面的起点距/高程点对转换成水位-面积-湿周表 distance: 起点距数组 (m) elevation: 对应高程数组 (m) z_min/z_max: 生成水位表的范围 dz: 水位间隔默认0.1m # 对断面点按起点距排序并做线性插值方便求交 order np.argsort(distance) d_sorted distance[order] e_sorted elevation[order] elev_interp interp1d(d_sorted, e_sorted, bounds_errorFalse, fill_value(e_sorted[0], e_sorted[-1])) z_nodes np.arange(z_min, z_max dz, dz) area_list [] perim_list [] for z in z_nodes: # 找到水位线与断面线的交点 wet_flag e_sorted z if not np.any(wet_flag): area_list.append(0.0) perim_list.append(0.0) continue # 左右岸交点用插值求 cross_idx np.where(np.diff(wet_flag.astype(int)) ! 0)[0] x_cross [] for idx in cross_idx: alpha (z - e_sorted[idx]) / max(e_sorted[idx1] - e_sorted[idx], 1e-9) x_cross.append(d_sorted[idx] alpha * (d_sorted[idx1] - d_sorted[idx])) left min(x_cross) if x_cross else d_sorted[np.where(wet_flag)[0][0]] right max(x_cross) if x_cross else d_sorted[np.where(wet_flag)[0][-1]] # 水下面积 梯形积分 wet_d d_sorted[(d_sorted left) (d_sorted right)] wet_e elev_interp(wet_d) area np.trapz(z - wet_e, wet_d) area_list.append(max(area, 0.0)) # 湿周近似 水下断面的曲线长度 if len(wet_d) 1: perim np.sum(np.sqrt(np.diff(wet_d)**2 np.diff(wet_e)**2)) else: perim 0.0 perim_list.append(perim) return z_nodes, np.array(area_list), np.array(perim_list)这段代码里的dz参数决定水位表的分辨率。默认 0.1m 对于大多数天然河道够用如果你的断面是窄深式比如山区峡谷河道水位抬升 0.1m 面积变化很大建议把dz减到 0.05m。np.trapz是梯形积分天然断面点距不均匀时这个函数会自动处理。注意湿周的计算用的是水下断面的曲线长度不是水面宽度——这两个值在宽浅河道里接近但窄深河道里差别很大会直接影响曼宁公式里的 R^(4/3) 项。3.2 边界条件与糙率上游来流、下游水位和分段的糙率场边界条件是这个资源里最需要理解的输入。一维圣维南方程组在数学上是拟线性双曲型方程组上下游在时间步进中需要给约束条件才能保证解唯一。这个资源的上游边界是“流量过程线”下游边界是“水位过程线或水位-流量关系曲线”。如果上游是水库放水直接给流量过程线如果下游是潮汐河口或受顶托的汇口给水位过程线如果是天然河道且下游有实测的水位-流量关系那就更理想模型会优先用这条关系做边界。边界文件同样是 CSV格式是两列time小时和value流量 m³/s 或水位 m。时间不要求等间距模型内部做线性插值但建议你的流量过程线涨水段至少 15 分钟一个点退水段可以放宽到 1 小时。流量过程线时间分辨率太粗是后面求解器发散的头号原因。糙率文件按断面分段给定。天然河道的糙率沿程变化很大主槽和滩地也不一样。资源里的糙率文件格式更简单每一行一个断面序号加一个糙率值。主槽糙率一般取 0.025 到 0.045有杂草或卵石的河段取 0.05 以上滩地糙率通常会比主槽大 0.01 到 0.02。如果是比赛或初步评价全河段给同一个糙率也能跑但你要意识到那只是“能跑”不代表率定。注意不同糙率断面的交接处也就是糙率发生突变的断面最容易出现局部水位台阶。这不是程序 bug而是物理上合理的——糙率大的河段水面线本来就会更陡。如果你不想让这个台阶太突兀用线性插值把糙率渐变过去而不是让两个断面之间直接跳变。3.3 数据读取与插值用 Python 把 CSV 变成模型可用的查表对象断面 CSV 和边界 CSV 准备好之后读取逻辑是这个资源的核心预处理模块。模型在时间步进中需要频繁查询“某断面在某水位下的面积”和“某断面在某水位下的湿周”所以资源里把每个断面封装成一个可调用的查表对象from scipy.interpolate import interp1d class RiverSection: def __init__(self, mileage, z_nodes, area_nodes, perim_nodes, manning_n): self.mileage mileage self.z_nodes z_nodes self.area_interp interp1d(z_nodes, area_nodes, bounds_errorFalse, fill_value(0.0, area_nodes[-1])) self.perim_interp interp1d(z_nodes, perim_nodes, bounds_errorFalse, fill_value(perim_nodes[0], perim_nodes[-1])) self.n manning_n def area_from_z(self, z): # 水位低于河底时面积返回0但实际计算中会通过最小水深保护避免出现0 return float(self.area_interp(min(max(z, self.z_nodes[0]), self.z_nodes[-1]))) def hydraulic_radius(self, z): a self.area_from_z(z) p float(self.perim_interp(min(max(z, self.z_nodes[0]), self.z_nodes[-1]))) return a / max(p, 1e-6)这里bounds_errorFalse是关键参数当水位低于断面表的最低水位时interp1d不会直接报错而是按fill_value返回 0。模型内部再配合最小水深保护第 4 章会讲就能实现干河床启动。如果你拿到这份资源后想改自己的数据只需要保持 CSV 的四列结构不变替换里面的数值即可读数据这部分代码基本不用动。4. 求解器运行与参数调优时间步长、迭代控制与初值处理4.1 主迭代循环残差、雅可比与追赶法的组装顺序求解器的主循环是典型的“预测—校正”迭代。每个时间步内做若干次 Newton 迭代每次迭代组装雅可比矩阵然后用追赶法求解修正量直到残差范数降到阈值以下。def solve_step(river, Q, Z, dt, theta, tol1e-6, max_iter20): 单个时间步的 Newton 迭代求解 river: 河道对象包含断面几何和糙率 Q/Z: 当前断面流量和水位数组上一时间步末值作为迭代初值 A np.array([river.sections[i].area_from_z(Z[i]) for i in range(river.n_node)]) for k in range(max_iter): res swe_residual(A, Q, Z, A_old, Q_old, Z_old, river, dt, dx, theta) norm_res np.sqrt(np.mean(res**2)) if norm_res tol: break # 数值差分组装雅可比矩阵 J assemble_jacobian(river, A, Q, Z, dt, dx, theta, eps1e-6) # 追赶法求解 J * delta -res delta thomas_solve(J, -res) Q delta[0::2] Z delta[1::2] A np.array([river.sections[i].area_from_z(Z[i]) for i in range(river.n_node)]) return Q, Z, norm_res这里的max_iter20不是随便给的Preissmann 格式在每个时间步内通常 3 到 5 次迭代就能收敛20 次是上限保护。如果你发现迭代次数经常顶到 20 还不收敛大概率不是迭代上限的问题而是时间步长太大或初值给得不对。assemble_jacobian里用的是数值差分而不是解析导数好处是实现简单、换断面几何函数时不用手动推导数代价是每个时间步多算几次残差。对几十个断面的河道这个开销完全可接受。迭代收敛后你要看一眼norm_res的变化趋势。一个健康的迭代过程应该是前几次迭代残差快速下降后面几次变化很小。如果你看到残差来回跳、不下降说明进入了振荡区间优先回头检查时间步长。4.2 时间步长与断面加密Courant 数只是参考不是铁律时间步长的选取是这个模型里最需要经验的参数。显式格式里 Courant 数是硬约束而隐式格式把约束放宽了但它并不是消失。资源里算 Courant 数用的是经典公式C (|u| c) * dt / dx其中 u 是断面平均流速c sqrt(gA/B) 是重力波波速B 是水面宽度。对隐式格式工程经验是 C 控制在 5 以内通常稳定C 超过 10 就要小心。但更直接好用的经验法则是看洪水的涨率。场景推荐时间步长 dt说明缓慢退水/枯季流量300 s水流接近恒定大步长够用一般洪水过程60 ~ 120 s标准防洪演算配置陡涨陡落的山区洪水10 ~ 30 s涨水段 15 分钟内流量可能翻倍上游水库泄洪骤变5 ~ 20 s流量在几分钟内跳变时最保守断面间距 dx 由数据决定但如果实测断面间距超过 500m建议在相邻断面之间线性插值加密一次。理由很实际Preissmann 格式在断面间距过大时水流在空间上的演化被强行拉平峰值水位会被低估。加密后峰值水位通常会抬高一些也更接近物理真实。4.3 初值与涨水过程干河床启动和边界 ramp 处理干河床启动是新手最容易翻车的地方。天然河道在枯季可能只有很浅的水甚至部分河段完全干涸。如果你直接把初始水位设成和河底齐平曼宁公式里的 A 为 0整个雅可比矩阵出现奇异第一步迭代就 NaN。资源里对这个问题的处理是“最小水深垫底”所有断面初始水位取河底高程加 0.1m让每个断面都有一层极薄的水。这层水不是物理真实但它的作用是让摩阻项可计算模型会在前几个时间步自动把它“冲走”或调整成真实形态。提示最小水深不要取得太大。0.1m 是经验值取 0.5m 以上的话相当于给河道预加了一部分水前几个时间步会产生虚假的退水过程影响你对结果前段的判断。边界流量突变是另一个发散源。如果用实测的陡涨流量过程线直接喂给模型第一个时间步的 dQ/dt 会非常大极易激起振荡。资源里提供一个 ramp 函数把边界流量在初始 30 分钟内从 0 逐渐抬升到目标值def ramp_up(Q_target, t, t_ramp1800): 对边界流量做软启动 Q_target: 原始流量过程线在 t 时刻的值 t_ramp: 软启动时长单位秒默认30分钟 if t t_ramp: # 用1.5次幂而不是线性保证初始时刻斜率连续 return Q_target * (t / t_ramp) ** 1.5 return Q_target用 1.5 次幂而不是线性的原因是线性函数在 t0 处斜率是常数阶跃导数在第一个时间步会造成虚假振荡1.5 次幂在 t0 处导数为 0连续性好得多。这也是从实践里踩出来的——线性 ramp 在 dt60s 时模型照样能跑但在 dt300s 时大概率会给你一个假的水位尖峰。5. 排查与避坑干河床启动、NaN 发散与 zip 伪加密的现场记录5.1 干河床启动就 NaN最小水深保护没生效现象模型第一步或前几步输出 NaN日志里面积或流量变成非数值。原因初始水位直接设成河底高程部分断面面积恰好为 0曼宁公式计算时 A² 在分母上雅可比矩阵出现奇异。还有一种常见情况是初始水位低于断面表的最低水位节点interp1d返回了 0而最小水深保护代码没有被正确触发。解决检查初值代码里是否对每个断面做了z_init max(河底高程 0.1, 断面最低水位节点)。另外确认RiverSection.area_from_z里min(max(z, z_min), z_max)这段夹取逻辑存在否则水位低于断面表范围时查表会返回 0。我一般会在模型跑之前单独打印所有断面的初始面积数组连续出现 5 个以上 0 就说明初值需要抬高。5.2 上游流量突增后水位振荡ramp 和 dt 要一起调现象计算不报错但水位过程线在涨水段出现周期性的尖刺波形像锯齿。原因最可能是上下游流量过程线的时间分辨率太低涨水段相邻两个数据点之间流量跳了 30% 以上导致边界条件的 dQ/dt 不真实。另一个原因是 dt 太大流量陡变在一个时间步内跨过太多断面。解决先把上游流量的时间插值加密到 15 分钟一点再对比结果。如果锯齿还在把 dt 从 60s 降到 20s 试一次。这里的经验是锯齿的波长如果等于 2 倍 dt就是时间步长的问题如果波长明显长于 2 倍 dt是边界条件的问题。分清这两个来源能省很多调试时间。5.3 θ 取 0.5 算出来的水位锯齿时间权重不是越大越好现象θ0.5理论上二阶精度更高时计算结果在水位平缓段出现小幅振荡但流量看起来正常。原因θ0.5 的 Crank-Nicolson 格式对高频分量没有足够的耗散天然河道这种摩擦项强烈非线性系统里数值振荡不容易被自然衰减。这是 format 本身的特性不是 bug。解决把 θ 调到 0.6 到 0.7 区间重新跑。这个包默认 0.65我个人的习惯是直接固定 0.65不再动它。精度上牺牲的那一点点时间精度在工程水位计算里完全可以接受换来的是稳定性和调试时间的节省。5.4 zip 伪加密与 EOCD 损坏下载后的第一道坎现象解压这个 zip 包时提示“需要密码”或者报错could not find EOCD、missing zip entry甚至 WinRAR 直接说文件损坏。原因zip 文件有 64 字节的尾部 EOCD 记录里面记录了目录偏移量。如果这个文件是伪加密也就是通用位标志里的加密位被误置成 1而实际文件并没有加密数据解压软件就会让你输密码。EOCD 报错则基本是下载不完整——某些网盘或浏览器下载中断后文件大小和正常值不一致。解决先用 7-Zip 打开 zip 文件看文件是否带星号加密标记。如果是伪加密用十六进制编辑器找到每个文件头的通用位标志General Purpose Bit Flag在文件头偏移 6 字节处两个字节把第 0 位从 1 改成 0保存后重新解压就能直接打开。如果是 EOCD 缺失检查下载文件的大小是否和资源页标明的字节数一致不一致就重新下载一致的话尝试用 7-Zip 的“修复”功能重建目录。遇到这种问题优先怀疑文件本身别急着怀疑你的解压软件。5.5 下游边界条件给错水位漂移无穷多解现象模型整个计算过程不报错流程很顺畅但下游断面的水位整体持续偏高或偏低看起来像整体平移了一段。原因一维圣维南方程组的边界条件组合必须满足“上游流量 下游水位”或“上游流量 下游水位-流量关系”这种形式。如果你上游给了流量、下游也给了流量等于说整个河段的蓄量变化没有水位锚点方程组在数学上有无穷多解最终解出来的水位取决于初始水位会整体漂移。解决把下游边界改成水位过程线或实测的水位-流量关系曲线。如果你的下游是水库回水区给水库水位过程线如果是天然河道给多年实测的水位-流量关系点对模型会在线性插值后作为边界使用。判断是否属于这个问题的技巧是改变初始水位后重新跑一遍如果下游段水位跟着初始水位整体移动那就是边界条件缺少水位约束。6. 结果验证与率定习惯用曼宁理论解对照再上真断面6.1 恒定流验证一维模型先过理论关拿到任何新断面数据我都不会直接跑洪水过程而是先做一次恒定流验证。做法很简单把边界条件设成上下游流量相同、且不随时间变化模型稳定后应该达到均匀流或渐变流状态。对于平直棱柱形河道模型算出的水深应当与曼宁公式直接求解的水深一致h (Qn / (B S₀^0.5))^(3/5)这里的 B 是水面宽度S₀ 是底坡。我一般用这个结果作为验收标准模拟水深和曼宁公式计算水深的差在 1cm 以内才算模型基础逻辑正确。如果对不上问题通常出在断面面积和水力半径的插值逻辑上而不是求解器本身。6.2 糙率率定的最小可行流程真实河道的后续率定核心是糙率反演。标准做法是从下游往上游分段试错先给全河段一个初值比如 0.035跑恒定流对比沿程水位站实测值哪一段模拟水位偏高说明该段糙率取大了降低糙率偏低则抬高糙率。每次只调一个河段每调一次跑一遍恒定流一般 3 到 5 轮就能把误差压到 0.1m 以内。这个方法看似笨但比一次性全河段调参可靠得多。从那以后我每次拿到新河道断面第一件事就是固定 θ0.65、最小水深 0.1m、恒定流验证这三件事不走完不上真洪水数据。模型真炸了先看质量守恒残差而不是怀疑程序——这个习惯帮我省下了大量调参的周末时间。这份资源的 zip 包本身也是按这个顺序组织的先跑自带算例做验证再替换自己的断面数据最后率定糙率。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →