
简介面向声子晶体梁带隙特性数值研究提供一份基于Timoshenko梁理论的12×12传递矩阵MATLAB计算脚本。Timoshenko梁计入剪切变形与转动惯量相比欧拉-伯努利梁更精确适合宽梁、薄壁梁等结构传递矩阵法将梁离散为若干子段通过局部矩阵连乘获得全局传递矩阵可高效处理周期性边界条件并求解频散关系。压缩包仅含1个m脚本整体约2KB代码模块包括参数定义、单元传递矩阵计算、全局矩阵组装、频率扫描与结果可视化结构清晰便于直接运行和二次修改。已有367人学习下载。读者可通过调整梁的几何尺寸、材料属性或周期排布参数方便地复现带隙结构观察频率响应曲线、带隙范围与模态形状为声隔离、声过滤等实际工程应用提供理论支持与数值参考。1. 十二乘十二的传递矩阵到底在算声子晶体梁的什么这片子聊的是一个很具体的计算问题把声子晶体梁拆成周期单元用 12×12 的传递矩阵扫出弯曲波带隙。这里的 12×12 不是装饰是 Timoshenko 梁模型下每个截面状态量的自然维度传递矩阵组装好之后带隙位置、宽度、衰减常数一次全给出来。很多人第一次接触声子晶体梁习惯直接套 Euler-Bernoulli 梁的四阶微分方程觉得状态量四个就够了结果算高阶带隙或者截面高宽比稍大时带隙中心和实验差得离谱。适合的读者很明确你在做周期梁、超材料梁、夹层梁的带隙分析或者要给后续的有限周期透射率、实验验证铺一个可复现的基准算法这篇文章就是给你一条从零搭起来的路径。2. 为什么状态向量凑成12维Timoshenko梁、双梁耦合与单胞矩阵2.1 声子晶体梁的带隙来源材料周期只是第一步声子晶体梁本质上是一维周期结构。你沿梁长方向周期性地改变截面尺寸、材料参数或者周期性地布置谐振单元弯曲波在传播时就会在布拉格频率附近发生散射某些频段内没有实数波数解波传不过去这就是带隙。计算带隙的手段有很多平面波展开、有限元特征频率法、谱元法以及本文要讲的传递矩阵法。传递矩阵法的好处是直观且省内存尤其适合“先扫频、后看趋势”的前期设计你不用建三维模型单胞矩阵乘起来就能得到色散关系和有限周期透射率。但声子晶体梁的麻烦在于梁理论的选择。Euler-Bernoulli 梁假设截面在变形后仍垂直于中性轴忽略剪切变形和转动惯量在长细比很大的细长梁、低频段是可靠的。可声子晶体梁为了压低频带隙往往把梁做厚、做短或者使用高宽比接近 1 的截面此时剪切变形对挠度的贡献不可忽略转动惯量对弯矩平衡的修正也开始显现。我一般在工程复现里直接上 Timoshenko 梁模型把横向位移、截面转角、弯矩、剪力四个量全部显式写出来剪切变形通过截面形状系数进入柔度项转动惯量通过惯性力矩进入弯矩平衡。这样做的代价是状态量变多但换来的好处是计算结果在高频段仍然可靠不会在带隙边界上翻车。2.2 Timoshenko梁与欧拉梁的分叉点什么时候必须用12×12这套重工具一个直观的判据是剪切变形的影响系数当梁的截面高度与波长之比超过 0.1 时Euler-Bernoulli 梁的相速度预测就会明显偏高。声子晶体梁带隙通常出现在第一布里渊区边界附近对应的波长很短正好落在这个误差区间。你如果拿 Euler-Bernoulli 梁算出的带隙中心频率去做实验经常会发现差出 10% 到 20%而且越往高阶带隙越离谱。把 Timoshenko 梁写成状态空间形式后每个截面的状态量是轴向位移、横向位移、截面转角、轴力、剪力、弯矩六个分量。为什么是六个因为弯曲和轴向振动在直梁里通常解耦但程序里一旦要处理轴向力耦合、或者后续要拼装任意方向的子结构把轴向位移和轴力一起放进状态向量反而省事。于是单根 Timoshenko 梁段的场传递矩阵是 6×6。那 12×12 从哪来常见的声子晶体梁模型里有一种是双梁夹层结构上梁、下梁各占一个 Timoshenko 梁中间是弹性连接层。上下梁之间靠分布式刚度互相牵扯位移差直接产生内力无法分别独立求解。这时把上梁的六个状态量和下梁的六个状态量合并成一个 12 维状态向量层间耦合就变成 A 矩阵里的线性刚度项整个单胞的传递矩阵自然就是 12×12。这套模型能同时覆盖“上下梁材料不同”“中间层刚度可变”“层间转动耦合”这些实际设计变量比单独的周期散射体模型更贴近夹层声子晶体梁的实物。2.3 12个状态量的落位轴向、横向、转角与内力的配对我习惯把 12 个状态量按固定顺序排布方便后面写矩阵时不出错。状态向量 y 依次是上梁的轴向位移 u1、横向位移 w1、截面转角 ψ1、轴力 N1、剪力 Q1、弯矩 M1然后下梁的轴向位移 u2、横向位移 w2、截面转角 ψ2、轴力 N2、剪力 Q2、弯矩 M2。传递矩阵 T 的作用是 y_right T × y_left把单胞左端面的 12 个分量映射到右端面。这样排布有一个直接好处上下梁之间的耦合项可以写成非常干净的刚度矩阵叠加。中间弹性层的纵向刚度 k_lon 连接 u1 和 u2剪切刚度 k_sh 连接 w1 和 w2转动刚度 k_rot 连接 ψ1 和 ψ2。这些耦合项加到 A 矩阵的对应行列里整个系统就是一个标准的 12 阶常微分方程组。你不需要去记忆复杂的四阶微分方程通解只需要在每个短梁段内求解这个状态方程的传递矩阵再把所有段乘起来就能得到任意长度和任意层间刚度的单胞传递矩阵。这也是我推荐用状态空间数值格式的原因公式推导一次到位后面改参数只改矩阵系数不碰算法骨架。3. 把12×12传递矩阵搭起来数值状态空间格式与可运行脚本3.1 分段积分求场矩阵expm是黑匣子但很好用直接解析推导 Timoshenko 双梁系统的 12×12 传递矩阵不是不行通解表达式会很长而且层间刚度一加进去符号推导就爆炸。工程上更常见的做法是先把控制方程写成状态空间形式 dy/dx A(x) y然后把梁段切成若干小段每段内假设材料参数和耦合刚度保持不变用矩阵指数 expm(A × ds) 得到这一段的状态转移矩阵。把所有小段的转移矩阵按顺序乘起来就是整个单胞的 12×12 传递矩阵。矩阵指数这个概念对很多人来说是黑匣子但实际用起来很稳。你只要保证 A 矩阵拼得对分段数足够expm 的结果就是这段微分方程组的精确积分。相比龙格库塔逐步积分expm 不累积局部截断误差且每段的计算量只跟矩阵规模有关。12×12 的矩阵指数在 scipy 里一秒钟能算几千个频率点扫频根本不用担心性能。3.2 最小Python实现从材料参数到单胞矩阵下面这段脚本是我在工程复现中最常用的骨架它包含三个部分构造单层 Timoshenko 梁的状态矩阵、拼出带层间耦合的 12×12 矩阵、积分得到单胞传递矩阵。代码不依赖任何自编公式全部由物理方程直接推导。import numpy as np from scipy.linalg import expm, eig def single_layer_A(omega, E, G, rho, A, I, kappa): 单层 Timoshenko 梁的状态矩阵状态顺序为 u, w, psi, N, Q, M。 A_mat np.zeros((6, 6), dtypefloat) # du/dx N / EA A_mat[0, 3] 1.0 / (E * A) # dw/dx psi Q / (kappa G A) A_mat[1, 2] 1.0 A_mat[1, 4] 1.0 / (kappa * G * A) # dpsi/dx M / EI A_mat[2, 5] 1.0 / (E * I) # dN/dx -rho A omega^2 u A_mat[3, 0] -rho * A * omega**2 # dQ/dx -rho A omega^2 w A_mat[4, 1] -rho * A * omega**2 # dM/dx Q rho I omega^2 psi A_mat[5, 2] rho * I * omega**2 A_mat[5, 4] 1.0 return A_mat def cell_matrix_12x12(omega, params, nseg8): 双梁夹层单胞的 12x12 传递矩阵。 params 中包含上下梁材料/截面参数和中间层刚度 k_lon, k_sh, k_rot。 p params L_cell p[L_cell] ds L_cell / nseg A_up single_layer_A( omega, p[E_up], p[G_up], p[rho_up], p[A_up], p[I_up], p[kappa_up] ) A_dn single_layer_A( omega, p[E_dn], p[G_dn], p[rho_dn], p[A_dn], p[I_dn], p[kappa_dn] ) A12 np.zeros((12, 12), dtypefloat) A12[:6, :6] A_up A12[6:, 6:] A_dn # 中间层纵向刚度N1 与 N2 方程中的耦合项 k_lon p[k_lon] A12[3, 6] k_lon # dN1/dx 受 u2 影响 A12[3, 0] - k_lon A12[9, 0] k_lon # dN2/dx 受 u1 影响 A12[9, 6] - k_lon # 中间层剪切刚度Q1 与 Q2 方程中的耦合项 k_sh p[k_sh] A12[4, 7] k_sh A12[4, 1] - k_sh A12[10, 1] k_sh A12[10, 7] - k_sh # 中间层转动刚度M1 与 M2 方程中的耦合项 k_rot p[k_rot] A12[5, 8] k_rot A12[5, 2] - k_rot A12[11, 2] k_rot A12[11, 8] - k_rot # 分段积分按顺序乘起来得到单胞矩阵 T_cell np.eye(12) U expm(A12 * ds) for _ in range(nseg): T_cell U T_cell return T_cell这段代码的逻辑很直白先拼出单层状态矩阵再通过索引把上下梁的状态矩阵塞进 12×12 的大矩阵第三部分把层间耦合刚度加到对应行列。耦合项的正负号需要特别留意对上述状态向量的定义N1 方程里出现的是 k_lon 乘以 (u2 - u1)所以对应 A12[3, 6] 加正号、A12[3, 0] 减正号下梁 N2 方程正好相反。剪切刚度和转动刚度同理按位移差的方向确定符号。如果符号颠倒了算出来的单胞矩阵就不再是无阻尼保守系统特征值的倒数对称性会被破坏后期排查会非常痛苦。参数说明上nseg 控制分段数最小可以取 4我一般取 8 到 16这个值直接影响高频段的收敛性。omega 的扫频步长决定带隙边界的分辨率建议先粗扫认形态再在带隙边界附近加密。中间层刚度的量级不要拍脑袋先按弹性模量除以厚度估算再扫一个数量级范围看带隙变化趋势。3.3 扫频判带隙特征值模长与色散曲线的读法拿到单胞矩阵 T_cell 之后带隙计算实际是求解 Bloch 特征值问题。周期结构的传播条件要求单胞两端的状态向量满足 Bloch 关系 y_right λ y_left其中 λ exp(i k L_cell)。于是问题变成求 T_cell 的特征值看它们是否落在单位圆上。完全无阻尼的情况下如果某个频率点所有特征值模长都等于 1这个频段是通带弯曲波能传播只要存在模长明显偏离 1 的特征值对应频段就是带隙波衰减的程度由 |λ| 的对数决定。我一般在程序里直接扫频把每个频率点的最大特征值模长取出来画一条曲线逻辑如下def scan_gaps(omega_list, params, nseg8): 返回每个频率点对应的最大特征值模长 max_abs [] for w in omega_list: T cell_matrix_12x12(w, params, nsegnseg) evs eig(T)[0] max_abs.append(np.max(np.abs(evs))) return np.array(max_abs)这条曲线在带隙区间会明显凸起因为特征值成对出现且互为倒数当最大模长大于 1 时必然存在小于 1 的配对值波呈指数衰减。画色散曲线则要更细一步对每个频率点取出特征值相位实部和模长虚部把实波数画在一边把衰减常数画在另一边。我常用的约定是横轴频率左纵轴实波数 Re(k)右纵轴衰减常数 Im(k)带隙在右半图表现为衰减常数从零跳升的区间。用这个判据时要设一个容差不然数值噪声会让你把通带误判成带隙。我习惯把容差设成 0.05 到 0.1最大特征值模长大于 1.05 或小于 0.95 才认为是带隙。如果扫频步长很粗带隙边界会平移到假位置所以定位带隙边界时要把步长加密到赫兹量级。3.4 试算参数表先复现再改造下面是铝-橡胶双梁夹层结构的一组常见参数适合做第一个跑通案例。铝层做上下梁橡胶层做中间连接。这个组合的好处是材料参数大家都很熟且阻抗差异足够大带隙明显跑完和文献趋势能对上。参数上梁铝下梁铝说明弹性模量 E70 GPa70 GPa各向同性剪切模量 G26.9 GPa26.9 GPa铝典型值密度 ρ2730 kg/m³2730 kg/m³密度差异不大没关系截面高×宽4 mm × 20 mm4 mm × 20 mm高宽比接近 0.2截面形状系数 κ5/65/6矩形截面惯性矩 I1.07e-10 m⁴1.07e-10 m⁴矩形截面公式单胞长度 L_cell0.1 m0.1 m决定第一带隙频率量级中间层的纵向刚度 k_lon 先按 1e7 N/m² 起步剪切刚度 k_sh 按橡胶剪切模量除以厚度估算转动刚度 k_rot 在初始阶段直接设 0等模型跑通再加。频率扫描范围建议从 100 Hz 扫到 5000 Hz第一带隙通常出现在几百赫兹到两千赫兹之间。如果带隙位置和你预想差太远优先检查单胞长度和截面尺寸而不是去调材料参数。4. 常见问题排查矩阵奇异、假带隙、耦合刚度玄学4.1 现象一算出来的带隙中心和实验差一截把结果拿去和实验对比时差出百分之二三十这是最常见的翻车现场。原因多半不是你程序写错了而是梁模型选得不对或者参数没对上。Euler-Bernoulli 梁在弯曲波波长较短时会高估相速度带隙中心频率整体偏高。还有一种情况是实验件的高宽比和模型不一致截面形状系数 κ 给错比如矩形截面应该用 5/6结果有人按圆形截面给成 0.9剪切柔度偏小带隙也会飘。解决的办法分两步。第一步把模型的参数表和实验件的几何参数逐项核对特别是截面高度、宽度和单胞长度这三个量直接决定惯性矩和单胞周期。第二步做一个模型切换测试把剪切变形和转动惯量项全部设成极小值对比 Euler-Bernoulli 和 Timoshenko 的带隙边界如果差异超过 5%就说明你的工作频段已经进入必须用 Timoshenko 模型的区间不要再去迁就简化模型。4.2 现象二通带里出现假禁带扫频曲线在某个通带频率出现一根突兀的尖峰看起来像带隙但用有限周期模型算透射率时这个频段却没有衰减这就是假禁带。假禁带通常来自特征值排序跳变。特征值是复数它们在复平面上随着频率移动到某一点时两条特征值曲线交叉程序按模长排序后会把不同枝的特征值混在一起导致模长突变。解决办法是不要只看单个特征值而是看整组特征值的对称性。无阻尼系统里特征值成对互为倒数如果某一枝跳变破坏了这种对称性基本可以断定是排序问题。我在扫频循环里会做一步连续性追踪对当前频率点的特征向量和上一频率点的特征向量做内积匹配内积最大的才认为是同一枝这样能有效避免排序跳变。更省事的方案是直接用最大特征值模长判断带隙因为成对对称性保证最大模长在通带里恒为 1假跳变会被容差过滤掉。4.3 现象三矩阵乘法越乘越不收敛分段数从 8 加到 16带隙边界不收敛甚至单胞矩阵的数值奇异这时候问题出在状态矩阵的动态范围上。Timoshenko 梁状态向量里包含内力和位移量纲差了好几个数量级位移大概是毫米级内力是千牛级两者乘在一起后矩阵条件数很容易爆炸。尤其在高频段A12 矩阵的特征值虚部很大expm 的结果会很强地放大微小数值误差。解决思路是给状态向量做量纲归一化。我习惯在拼 A12 之前把力分量除一个参考力 F_ref把弯矩除一个参考弯矩 M_ref位移和转角保持不变矩阵变为无量纲形式。这样 expm 的动态范围小很多分段数加到 32 之后结果依然稳定。也可以反过来把位移分量乘一个大数但不如归一化力分量直观。即使不打算改代码骨架至少要做分段收敛性检验nseg 从 4 到 32带隙边界变化小于 2% 才算收敛。4.4 现象四中间层刚度扫不出带隙耦合刚度 k_sh、k_lon 设了一大堆值带隙纹丝不动。这个现象很常见尤其是把 k_lon 设得超大时上下梁被完全锁成一体系统退化成一根厚梁带隙只能靠布拉格散射产生。反过来k_sh 设得太小上下梁几乎独立夹层梁退化成两根孤立梁带隙主要来自单根梁自身的长度周期和你要设计的夹层带隙不是一回事。处理这类问题的核心是先扫刚度-频率二维图横轴频率、纵轴 k_sh 的对数值用颜色画最大特征值模长。这样你能一眼看出带隙从哪里冒出来、刚度在哪个量级范围内有效。我一般在 1e6 到 1e10 内按对数取 20 个点扫描看带隙是否连续移动。如果整个二维图里都没有明显的高衰减区再回头检查 A12 耦合项的符号尤其是转动刚度 k_rot它经常因为正负号反了而把带隙直接抹掉。5. 验证与进阶用透射率校核带隙把单胞矩阵当积木5.1 有限周期透射率的计算是做实验前最该补的一步。单胞矩阵求出的色散带隙是无限周期结构的性质实验件只有有限周期结果会因为端部反射和近场效应产生偏差。把 N 个单胞矩阵按顺序连乘得到总传递矩阵 T_total T_cell^N然后在一端施加力和位移边界条件另一端提取响应位移位移比就是透射率。代码实现里我通常只用两块一段连乘循环一段线性方程求解。边界条件建议两端都用自由边界左边给单位剪力右边提取横向位移虽然和实验夹持方式不完全一致但作为带隙验证已经足够。5.2 与 FEM 或实验对齐时我按下面三个可执行校验来验收。第一检查单胞矩阵特征值成对倒数对称性误差超过 1% 说明代码里有符号或参数错误。第二做分段收敛检验带隙边界随 nseg 变化的漂移量控制在 2% 以内这个检验同时也是判断 Timoshenko 梁模型是否必要的手段。第三对比有限周期透射率的陷波频率和无限周期带隙边界两者偏差通常不应超过一个扫频步长如果偏差变大优先怀疑中间层刚度参数估算不准。最后讲一个我自己的习惯。每次新建一个声子晶体梁项目我都会把材料参数、截面尺寸、单胞长度、扫频范围和分段数存成一个配置字典每个算例只改配置不改算法。这样做的好处是复现快换材料、换截面只需要一次扫描就能看到全部带隙变化不用在代码里翻来翻去。之前有一次我把上梁和下梁的惯性矩写反了结果带隙中心偏了一个数量级查了半天才在配置里发现低级笔误。那之后我每次跑完都顺手把矩阵无量纲化、把特征值对称性打印出来看一眼能省下大量排错时间。这套 12×12 传递矩阵方法本身不难难的是把每个环节都做得有据可查。希望帮到你。本文还有配套的精品资源点击获取