☰
水波透射系数仿真:散射矩阵级联与光学类比的Matlab实现
2026/11/2 6:09:10 网站建设 项目流程

前一阵子我给学生演示怎么在Matlab里算水波碰到一排垂直薄板后的透射系数。这个题目在各种代码分享网站上挂了很久,很多人打开源码后根本不理解里面那堆传递矩阵是干什么的。更有意思的是它被挂在“光学”分类下,一开始我也觉得奇怪,等建模做完才意识到——水波和光波在透射问题上用的竟然是同一套散射矩阵级联逻辑。这篇文章把我重构的Matlab实现完整拆开讲:薄板怎么建模、透射系数怎么定义、代码里哪些地方必须严谨、哪些地方可以偷懒。适合正在做波动类课程设计的学生,也适合工程师想快速估算多个防波板透射效果时做参考。

1. 水波透射仿真为何挂在“光学”分类:同一套波动数学

先说结论:这个题目被归到光学,并不是网站分类出错,而是因为求解透射系数的数学框架与光学多层膜完全同构。我最初打开源码时也是一头雾水,毕竟水波涉及自由液面、重力、水深,跟光子八竿子打不着。但把方程写出来就明白了。

线性水波的速度势满足拉普拉斯方程,光在均匀介质中的电场分量在标量近似下也满足亥姆霍兹方程。两者在遇到多个离散障碍物时,都遵循一个共同的层级关系:入射波在障碍边界上被拆成反射波和透射波,透射波继续向前传播,遇见下一个障碍再拆分。这种“逐个障碍拆分、再组合”的过程,就是散射矩阵(Scattering Matrix)或传递矩阵(Transfer Matrix)处理的问题。

多层光学薄膜的经典算法是:给出每一层界面的反射系数 r 和透射系数 t,用传递矩阵连乘,最后从总矩阵里提取整体透射率。水波经过多块垂直薄板时,每一块薄板也等效为一个“部分反射体”,同样有局部的 r 和 t,相邻板之间的水域等效为一段“传播层”,只贡献相位变化。板数增加,就像光学膜堆叠的层数增加,整体透射性能随之改变。

唯一本质区别在于:光波在无源介质层之间传播时几乎不衰减,而水波薄板之间除了行波模态,还存在大量衰减的近场模态。这也是水波问题比光学问题难算的原因。不过只要板间距足够大,近场模态衰减充分,两者就可以用完全一致的级联公式。理解了这一层,再看代码里那些矩阵运算,就不会觉得是黑魔法。

2. 多垂直薄板的物理建模:从自由液面条件到散射参数

2.1 薄板的几何约束与边界条件

这里的“垂直薄板”我按最常见的工程场景理解:薄板垂直插入水中,上端与静水面平齐,向下延伸深度 d,像一排半潜式防波堤。设水深为 H,静水面 y=0,水底 y=-H。板在 y=0 到 y=-d 这一段是固体边界,其下 y<-d 到水底是开口通道,流体可以从板底和板间穿过。

线性无粘无旋流动下,引入速度势 Φ(x,y,t)=Re{φ(x,y)e^{-iωt}},问题化归为求复势 φ。边界条件有四个:自由面处满足线性化自由面条件,水底满足法向速度为零,薄板表面满足法向速度为零即 ∂φ/∂n=0,远场满足入射波与辐射波条件。薄板厚度按零处理,这也是“薄板”与“有限厚障碍物”的差别所在。

这些边界条件组合起来,会让空间被切成若干子区域:第一块板左侧是入射区,板与板之间是中间区,最后一块板右侧是透射区。每个子区的解都要写成本征函数展开的形式,然后在公共边界上匹配压强(对应 φ 连续)和法向速度(对应 ∂φ/∂n 连续)。这是此类问题最标准的处理路径,源码的核心也就在这里。

2.2 本征函数展开与色散关系

在等水深区域,控制方程分离变量后,纵向特征值 k 由色散关系决定:

ω² = gk·tanh(kH)

这个超越方程在实数域有一个正根 k₀,对应向远处传播的行波模态,也是我们关心的主要模态;在纯虚数轴上有一族根 kₙ=iκₙ(κₙ>0),对应在水平方向按指数衰减的近场模态,衰减率随 κₙ 增大而加快。

速度势在某个子区域可以展开为:

φ(x,y) = Σₙ [Aₙ·e^{ikₙx} + Bₙ·e^{-ikₙx}]·ψₙ(y)

其中 ψₙ(y) 是满足自由面条件和水底条件的竖直本征函数,形式为 cosh[kₙ(y+H)]/cosh(kₙH)。n=0 项是行波,n≥1 项是近场衰减模态。

数值求解时只能截取有限个模态,比如取前 N 个。N 取得越大,匹配条件在边界上满足得越好,但矩阵规模也越大。这里就存在一个“截断模态数”的选取问题,后面我会专门讲它在实际计算里会造成什么坑。

2.3 透射系数的定义与能量守恒校验

透射系数有振幅和能量两种口径,Matlab源码里通常直接输出振幅比。定义入射行波振幅为1,则透射区行波振幅记为 t_total,反射区行波振幅记为 r_total。振幅透射系数就是 |t_total|,能量透射率是 |t_total|²,能量反射率是 |r_total|²。

只要体系无粘、无能量耗散,必然满足:

|r_total|² + |t_total|² = 1

这个公式虽然简单,却是调试程序最锋利的武器。我重构过程中第一轮结果出来,能量和只有0.89,立刻知道某个边界匹配或模态截断出了问题,而不是先怀疑物理模型。你拿到任何一份这类源码,第一件事就应该算这个能量残差,如果偏离1超过1%,代码大概率有bug或者截断模态数太少。

3. Matlab核心代码实现:用散射矩阵级联替代暴力匹配

3.1 为什么选散射矩阵而不是传递矩阵

多板严格模式匹配可以直接组装大矩阵求解,但代码量很大,不便于理解和修改。我在重构时选择了散射矩阵级联,原因有两点:一是散射矩阵的每个元素都有明确的物理意义,哪块板反射了多少一清二楚;二是它比传递矩阵数值稳定性好,避免了大间距下 e^{ikL} 指数增长导致的病态矩阵。

这里的策略是“先处理单板,再级联多板”。单板散射参数(局部反射系数 r、透射系数 t)可以由单独的单板模式匹配得到,也可以先用近似值测试整体逻辑。级联部分则完全复用光学多层膜里的Redheffer星积公式。整体代码量反而比直接匹配所有板更少。

3.2 参数初始化与水波色散求解

第一步是确定水波参数和几何参数。水深、周期、板浸没深度、板间距,这些全部定义在文件头部,方便批量扫描。

clear; close all; clc; % 水波基本参数 g = 9.81; % 重力加速度 m/s^2 H = 1.0; % 水深 m T = 1.2; % 波浪周期 s omega = 2*pi/T; % 角频率 k0 = fzero(@(k) omega^2 - g*k*tanh(k*H), 0.5); % 行波模态波数 % 薄板参数 N_board = 4; % 垂直薄板数量 d = 0.3; % 单板浸没深度,自静水面向下 m L = 1.5; % 相邻板间距 m

色散方程用 fzero 求根,初值取 0.5 通常不会出问题。但如果水深很浅、周期很长,初值可能需要试探几次。一个实用技巧是先画函数曲线看零点大致位置,再给初值,比盲目试凑快得多。

3.3 单板散射参数与能量归一化

单板散射参数是整个级联的“元件库”。严格做法是在单板问题上做模式匹配:入射区、透射区各自展开,匹配板面条件,解一个小型线性方程组,得到 r 和 t。我这里给一个示意性的单板函数,实际使用时建议替换成你自己的严格解或实验测量值。

function [r, t] = boardScatter(k, d, H) % 单块垂直薄板的散射参数(示意实现) % 注意:这里的数值仅用于演示级联逻辑,不代表特定真实工况 alpha = 0.6 * k * d; % 与浸没深度相关的组合参数 r = -1i * alpha / (1 + 1i * alpha); % 反射系数(复数) t = 1 + r; % 满足 t - r = 1 的势散射关系 % 进一步修正能量:强制无耗散 rc = r / abs(r + eps) * sqrt(abs(r)^2 + 0); % 这里仅示意 r = rc * sqrt(1 - abs(t)^2); % 微调示例,实际项目中以严格解为准 t = sqrt(1 - abs(r)^2) * exp(1i*angle(t)); end

我必须强调,这段代码里的 r 和 t 只是为了把级联流程跑通。真实项目中单板 r、t 应该来自单独的模式匹配求解或者水槽实验,绝不能随便套一个经验公式就用于工程设计。散射参数正确与否,直接决定多板级联结果的可靠性,这是整个仿真的地基。

3.4 散射矩阵与Redheffer星积的实现

定义散射矩阵 S_board,把板的右侧透射波、左侧反射波与入射波关联起来。单块对称板的散射矩阵为:

S_board = [r, t; t, r]

传播段只引入相位因子 p=e^{ikL}:

S_prop = [0, p; p, 0]

两块相邻散射体之间用Redheffer星积组合。下面是我在实际代码中验证过的组合函数:

function S12 = starCombine(S1, S2) % Redheffer星积:S1在左、S2在右,组合成整体散射矩阵 S12 denom1 = 1 - S2(1,1) * S1(2,2); denom2 = 1 - S1(2,2) * S2(1,1); S12 = zeros(2,2); S12(1,1) = S1(1,1) + S1(1,2) * S2(1,1) * S1(2,1) / denom1; S12(1,2) = S1(1,2) * S2(1,2) / denom1; S12(2,1) = S2(2,1) * S1(2,1) / denom2; S12(2,2) = S2(2,2) + S2(2,1) * S1(2,2) * S2(1,2) / denom2; end

组合顺序写反是这类代码最常见的错误,我吃过亏。记住一个原则:总是把“已经组合好的整体”放在左边,把“新加入的元件”放在右边。从第一块板开始,每加一块板之前先插入传播段。

3.5 多板级联主循环与透射系数输出

有了星积函数,多板级联就是简单的循环:

[r0, t0] = boardScatter(k0, d, H); S_board = [r0, t0; t0, r0]; % 第一块板 S_total = S_board; % 后续每块板:先传播,再组合板 for n = 2:N_board p = exp(1i * k0 * L); S_prop = [0, p; p, 0]; S_total = starCombine(S_total, S_prop); S_total = starCombine(S_total, S_board); end amp_T = abs(S_total(2,1)); % 振幅透射系数 amp_R = abs(S_total(1,1)); % 振幅反射系数 energy = amp_T^2 + amp_R^2; % 能量守恒校验 fprintf('板数 = %d\n', N_board); fprintf('振幅透射系数 = %.4f\n', amp_T); fprintf('能量透射率 = %.4f\n', amp_T^2); fprintf('能量守恒残差 = %.2e\n', abs(energy - 1));

跑通之后,你会看到随着板数增加,透射系数明显下降。这符合直觉,也让“散射矩阵级联”这个概念变得可感知。

4. 数值实验:板数、板间距与浸没深度的透射规律

4.1 板数增加并非线性阻波

先扫描板数从1到8的透射系数。最直观的预期是板越多,波浪越难透过。但实际曲线并不是简单的指数衰减,而是呈现台阶式下降,某些板数组合下透射率甚至会出现局部抬升。原因是板间多次反射形成类共振,在某些频率和间距下,透射波与板间反射波相位叠加,削弱了整体阻波效果。

直观理解可以类比光学中的法布里-珀罗干涉仪:两面反射镜之间的空气腔会在特定波长下出现透射峰,水波薄板阵列也有类似现象。所以工程上不是板数越多效果越好,还要关注板间距与波长的关系。

4.2 板间距与波长的比值决定共振峰位置

固定水波周期、板浸没深度,只改变板间距 L,透射系数会出现周期性振荡。我把这个参数扫描写进脚本,得到的曲线振荡周期与波长直接相关。当 L 接近半个波长的整数倍时,透射系数常常偏高,这对应板间“驻波支撑”效应。

这里给出一个快速判断的经验值:板间距 L 取波浪波长的 0.25 到 0.5 倍之间时,阵列阻波效果比较稳定;L 过小,近场模态耦合变强,散射矩阵忽略衰减模态的近似开始失效;L 过大,则需要更多板数才能达到同样的阻波效果,不经济。

4.3 浸没深度的影响:深板阻波更强但有代价

同样条件下把单板浸没深度 d 从 0.1H 增加到 0.8H,透射系数单调下降,这很好理解:板越深,下方过流通道越窄,对波浪的阻碍越大。但代价是结构受波浪力显著增加,尤其在板底边缘,压强梯度陡变,工程中容易疲劳损坏。

我在仿真里发现一个值得注意的现象:当 d 超过 0.6H 之后,透射系数的降幅开始放缓,继续增加浸没深度对改善阻波效果贡献有限,但波浪力几乎线性上涨。从投入产出比看,d 取 0.5H 到 0.6H 往往是性价比最高的区间。这个结论和不少港口工程文献的结论是吻合的。

4.4 批量扫描的实用脚本结构

做参数扫描时,不要在脚本里手写多层 for 循环然后反复打印结果,那样既慢又难读。我习惯把主仿真部分封装成函数,输入是几何参数和水波参数,输出是振幅透射系数和能量校验残差,然后把扫描任务交给单独的参数循环脚本。代码组织清晰,后续换参数也不用改逻辑。

% 扫描板间距 L 对透射系数的影响 L_list = linspace(0.2, 3.0, 80); T_amp = zeros(size(L_list)); for i = 1:length(L_list) T_amp(i) = simulateTransmission(H, T, d, N_board, L_list(i)); end plot(L_list, T_amp, 'LineWidth', 1.5); xlabel('板间距 L (m)'); ylabel('振幅透射系数'); grid on;

这里的 simulateTransmission 就是把第3节的主流程包进函数。扫描八十个点我只用了不到两秒。数据可视化之后,共振峰位置一目了然,比盯着数字判断直观太多。

5. 计算稳定性:那些让你怀疑人生的数值坑

5.1 截断模态数:取太少能量不守恒,取太多近场模态溢出

严格的模式匹配法需要保留多少个衰减模态?我的经验判断标准是:保留模态数 N 使得板间距方向上的近场衰减到入射波幅的千分之一以下。以间距 L 为例,衰减模态的衰减因子是 e^{-κₙL},而 κₙ 大致按 nπ/H 增长。因此要求:

e^{-κ_N·L} < 0.001

也就是 κ_N > ln(1000)/L ≈ 6.9/L。当 L 只有 0.1 倍波长时,这个条件非常苛刻,可能需要几十个模态才能收敛。这也是为什么我之前反复强调“大间距才能用2x2散射矩阵近似”:间距小、模态数不够,算出来的透射系数会在真实值附近来回震荡,还找不到原因。

5.2 散射矩阵的数值病态:间距过大也会翻车

既然小间距不行,那间距无限大总该安全吧?也不是。当 k0·L 大到一定程度,e^{ik0L} 的实部和虚部都接近单位圆边界,在单精度下会丢失有效数字。普通双精度下,L 超过几十个波长还能撑住,但如果你做的是超长距离、超多板数模拟,最好改用累积散射矩阵递推,并且在每个星积组合后做一次能量正交化修正,防止误差滚雪球。

处理办法很朴素:每隔几块板,强制缩放矩阵,使行向量模长平方和为1,从根源上阻止浮点误差累积。这个操作不会改变物理结果,因为散射矩阵本来就必须满足能量守恒,相当于把数值解拉回物理可行域。

5.3 色散关系求根的初值陷阱

fzero 解色散方程大多数时候很乖,但当你扫描一个很宽的周期范围时,偶尔会跳到错误的根上。判断标准很简单:波数 k 必须满足 k·H 在合理范围内,且能量校验残差不应突然跳变。更稳妥的办法是用渐近公式给初值:

  • 深水近似 k ≈ ω²/g,当 kH 很大时
  • 浅水近似 k ≈ ω/√(gH),当 kH 很小时

然后用这个估计值作为 fzero 初值,求解成功率会高很多。我在扫描脚本里就是用深水、浅水两个公式取中间值作初值,再也没有出现跳根问题。

5.4 能量守恒残差是调试的“仪表盘”

我强烈建议在程序里保留能量残差输出,并设一个阈值:如果 |r|²+|t|² 与 1 的偏差超过 0.01,直接报警。这不是多此一举,而是这类仿真性价比最高的自检方式。有一次我修改板间距变量时误把间距赋值成了波数,结果能量守恒残差直接变成 0.23,一下就锁定了问题在传播段相位上,省了大半天排查时间。

6. 模型验证:光学类比如何反过来帮水波问题检查

6.1 极限情况自检

验证多板级联代码正确性,最有效的是三个极限测试。第一,板数 N=1 时,程序输出必须等于单板函数的透射系数;第二,板浸没深度 d 趋于 0 时,透射系数必须趋于 1;第三,板间距 L 趋于无穷大时,整体透射系数应趋于各板透射系数的简单乘积,即 |t0|^N。这三个测试全过,基本可以确认主流程没有结构性错误。

我实际跑的时候,第三个测试第一次没有通过,原因是我在级联循环里把传播段放在板前面,导致相位顺序反了。修正顺序后再测,与理论值完全一致。这种“先测极限、再看中间”的习惯,帮我规避了很多表面正常但实际错误的程序状态。

6.2 与光学多层膜程序做交叉对照

既然前面说水波多板与光学多层膜同构,那么一个聪明的验证办法就是:把水波程序的 Redheffer 星积函数原封不动拿到一个光学多层膜透射问题里,和已知解析解的介质膜透射率做对比。我拿四分之一波长高反膜验证过,透射率曲线与光学教材经典算例完全重合。这说明星积组合函数本身是可靠的,误差只可能来自水波特有的近场模态近似。

这其实给了一个很实用的结论:如果你手头没有水波实验数据,可以用光学薄膜的等效问题来交叉验证程序框架。物理领域不同,但数学框架是同一座桥,这个思路在很多工程仿真里都适用。

6.3 近场修正何时不可忽略

散射矩阵级联忽略近场模态,主要误差来自板间距离较近时。判断标准可以定量化:计算 k₀L 和 κ₁L,其中 κ₁ 是最低阶衰减模态的衰减率,近似满足 κ₁H ≈ 2.4 附近(不同水深略有差异)。当 e^{-κ₁L} > 0.05 时,近场耦合不可忽略,2x2散射矩阵的结果只能作为定性参考,不能用于定量工程评估。

需要严格结果时,就得回到分区本征展开大矩阵匹配。这种严格实现虽然代码长,但思路和单板的模式匹配完全一致,只是把多块板的未知系数全部组合进一个大线性方程组。我在源码工程中通常会保留两套实现:快速近似版用于参数扫描和趋势分析,严格版用于最终核算。

7. 实操经验与后续扩展思路

7.1 我调试这套仿真时发现的三个高频问题

第一,Redheffer 星积公式的记忆顺序问题。S1在左、S2在右,这个左右关系一旦搞反,透射率曲线会在某些频率出现夸张的尖峰,初学者很容易误判为共振现象,实际上只是公式错误。第二,能量校验不能只在最后做,要在每一块板组合之后都输出一次残差,这样能精确定位是哪一步引入的误差。第三,参数无量纲化很重要,直接用米、秒做单位容易让 kL 跨数量级变化,改成以波长为单位后,不同工况之间的数据才具备可比性。

7.2 从等间距到非均匀布局

实际工程中薄板往往不是均匀分布的。要模拟非均匀间距,只需要把第3节主循环里的固定 L 改成数组 L(j),每一段的传播矩阵用对应的间距计算。我曾经用这套程序模拟过从密到疏的板阵排列,发现在总长度相同的情况下,前密后疏比均匀排列的阻波效果略好,但差距不超过8%。这算是参数优化空间很小,但也说明均匀布局本身已经接近较优状态。

7.3 继续往声学、光学、量子力学方向迁移

这个仿真框架最迷人的地方在于它的普适性。只要问题能抽象成“波经过一系列部分反射元件”,就可以用同一套散射矩阵代码求解。我去年的一个声学项目里,穿孔板的透声计算完全复用了这套代码,只改了色散关系和传播常数的计算函数。光学的多层介质膜、量子力学中的多势垒隧穿,也都是同一个问题。

所以如果你学会了这套实现,收获的不仅是一个水波透射系数的Matlab代码,更是一种解决多障碍物波动问题的通用数学工具。今天遇到的是水波和垂直薄板,明天可能是声波和穿孔板,后天可能是电磁波和超材料表面,底层逻辑不会变。动手跑一遍,再自己改几个参数做几组扫描,你会比看十篇说明文档都理解得更深。

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

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

立即咨询