用MATLAB实现悬臂梁有限元分析:从Hermite单元到弯矩图

发布时间:2026/9/16 11:38:44
用MATLAB实现悬臂梁有限元分析:从Hermite单元到弯矩图 简介面向结构力学与数值仿真学习者这份资源提供基于有限元法求解悬臂梁弯曲问题的完整MATLAB实现。代码采用参数化编程矩阵参数可灵活更改注释细致便于二次开发与算法理解同时附带可直接运行的案例数据适用于计算机、电子信息工程、数学等专业的学生完成课程设计、期末大作业或毕业设计。压缩包共包含13个文件其中9个为.m脚本、3个为.jl脚本、1个为.md说明文档能够同时展示MATLAB与Julia两种语言实现并覆盖形函数、单元刚度矩阵、全局刚度矩阵组装等核心模块有助于对照理解有限元求解流程。代码模块划分清晰参数调整方便可直接替换材料参数或梁截面尺寸进行扩展验证。整包仅7KB轻量便于快速获取。目前已有182人学习浏览对于需要短时间掌握悬臂梁有限元建模思路的读者而言是一份高效实用的参考。1. 悬臂梁弯曲问题材料力学公式失效时的通用解法材料力学课本能直接给出悬臂梁自由端的挠度、转角闭式解可一旦换成变截面、分段均布载荷或需要在同一根梁上组合集中力和分布力手推公式就会很狼狈。有限元法把梁离散成有限个欧拉-伯努利梁单元每个单元用 Hermite 形函数描述挠度和转角再组装成整体刚度方程求解。这个算例在结构分析和有限元入门里是标准练习因为不依赖任何有限元工具箱核心代码可以控制在 60 行以内。下面从控制方程的弱形式开始推把这一段在一个 MATLAB 脚本里完整跑通并和解析解比较最后告诉你如何从位移结果里再把弯矩图恢复出来。2. 有限元法求解梁弯曲问题的理论基础2.1 控制方程与弱形式为何要先做变分处理对等截面欧拉-伯努利梁静力弯曲控制方程为EI v q(x)有限元法不直接解这个四阶常微分方程而是把它变成虚功方程设 w 为满足固定端约束的虚位移场对全梁分部积分后得到∫ EI v w dx ∫ q w dx这个形式只要求积分里有二阶导数单元插值函数只需保证 C1 连续。悬臂梁在两个边界上的本质条件只有固定端 v(0)0 和 θ(0)v(0)0自由端的弯距与剪力是自然边界条件求解后自动满足。所以做约束处理时只删两个自由度整根梁的 K 矩阵不会出现零主元。2.2 Hermite形函数与四阶刚度矩阵的物理含义单元每个节点有挠度和转角两个自由度于是两节点单元的自由度顺序记为 [v1, θ1, v2, θ2]。用局部坐标 ξx/Le 定义的四条三次 Hermite 基函数是N1 1 - 3ξ² 2ξ³对应节点1单位挠度 N2 Le(ξ - 2ξ² ξ³)对应节点1单位转角 N3 3ξ² - 2ξ³对应节点2单位挠度 N4 Le(ξ³ - ξ²)对应节点2单位转角。它们保证单元两端挠度和转角各自连续这正是一维梁单元与桁架杆单元最本质的区别。把 N 代入单元势能积分得四阶单元刚度矩阵| 12 EI/Le^3 6 EI/Le^2 -12 EI/Le^3 6 EI/Le^2 | | 6 EI/Le^2 4 EI/Le -6 EI/Le^2 2 EI/Le | | -12 EI/Le^3 -6 EI/Le^2 12 EI/Le^3 -6 EI/Le^2 | | 6 EI/Le^2 2 EI/Le -6 EI/Le^2 4 EI/Le |第一列的含义是让 v11 而其余自由度为零需要在节点1施加向上的力 12EI/Le³ 和逆时针弯矩 6EI/Le²同时节点2配套向下力 -12EI/Le³ 和逆时针弯矩 6EI/Le²。其余各列同理。这样理解的好处是组装时能直观检查力的平衡任意一列四个分量之和力方向分量和应为零弯矩分量和应等于该列力对单元形心的矩。2.3 一致载荷向量和固定端约束的数学处理均布载荷 q 在单元左右节点上的等效节点力不是简单地 qLe/2 分到两个节点还伴随一对端部等效弯矩。推导得到的载荷向量为fe qLe/12 [6, Le, 6, -Le]^T其中第二个自由度方向在坐标取向右为正、顺时针转角为正时左端等效弯矩为 qLe²/12右端为 -qLe²/12。不要漏写这个弯矩项否则粗网格下端部挠度和转角都会偏小。集中力 P 作用在节点 j 时只需在全局载荷向量 F(2j-1) 处叠加 P集中弯矩 M 作用在节点 j 则叠加到 F(2j)。整体求解采用“先组装、后约束”的流程把固定端自由度从方程组中剔除只解自由自由度子块避免对全矩阵做手工行交换。3. MATLAB实现从节点坐标到挠度曲线的完整脚本3.1 物理参数与网格生成统一单位是第一要务这里的实现按经典三步走生成节点、组装、加约束求解。整个流程的数学基础非常对称单元数增加时只有 K 和 F 变化。一个直接的参数与网格部分如下。clearvars; close all; clc; % 物理参数采用 m-N-Pa 一致单位制 E 210e9; % 弹性模量 b 0.03; % 梁宽 h 0.06; % 梁高 I b*h^3/12; % 惯性矩 L 1.0; % 悬臂梁长度 q -1000; % 均布线载荷, N/m 向下取负 % 网格 nEl 8; % 单元数 nnp nEl 1; % 节点数 x linspace(0, L, nnp); Le diff(x); % 每单元长度不少初学实现栽在单位制长度用了 mm 而弹性模量用 Pa即 N/m²惯性矩按 mm⁴代入EI 直接差 10^12 倍。这里统一按米、牛顿、帕斯卡计算最后绘图时再转成毫米。3.2 组装全局矩阵自由度编号与稀疏矩阵全局自由度编号规则是节点 i 对应 2i-1挠度、2i转角。单元左节点编号 n1e右节点 n2e1于是单元自由度映射为 edof [2n1-1, 2n1, 2n2-1, 2n2]直接靠这个索引做四阶矩阵的 scatter 叠加。组装循环见下面代码块。nDofs 2*nnp; K sparse(nDofs, nDofs); F zeros(nDofs, 1); for e 1:nEl ke beamStif(E, I, Le(e)); fe beamLoad(q, Le(e)); n1 e; n2 e 1; edof [2*n1-1, 2*n1, 2*n2-1, 2*n2]; K(edof, edof) K(edof, edof) ke; F(edof) F(edof) fe; end稀疏矩阵 K 在这里不是可有可无的优化单元数为几百时满矩阵也能算过千后稀疏与稀疏分解的速度差异就到数量级。MATLAB 的sparse会在重复索引叠加时自动累加不需要自己处理冲突。3.3 两个子函数单元刚度与一致载荷向量function ke beamStif(E, I, Le) % Hermite 梁单元刚度自由度顺序 [v1, th1, v2, th2] ke E*I/Le^3 * [ 12 6*Le -12 6*Le; 6*Le 4*Le^2 -6*Le 2*Le^2; -12 -6*Le 12 -6*Le; 6*Le 2*Le^2 -6*Le 4*Le^2]; end function fe beamLoad(q, Le) % 均布载荷一致节点力q 向上为正转角自由度按逆时针为正 fe q*Le/12 * [6; Le; 6; -Le]; end这里的关键是符号约定全梁规定挠度向上为正、转角逆时针为正。将 q 取负后自由端挠度数值为负正好对应向下挠曲。如果原先设计为“向下为正”的计算体系需要把这一条在模块入口处统一否则后续恢复弯矩图时会栽在正负号问题上。3.4 边界处理、求解与解析解对比固定端节点编号为1需要约束的全局自由度是 1 和 2。实现上不修改 K 矩阵而是先选出自由自由度索引求解后再把结果回填到完整的位移向量。fixedDofs [1 2]; freeDofs setdiff(1:nDofs, fixedDofs); u zeros(nDofs, 1); u(freeDofs) K(freeDofs, freeDofs) \ F(freeDofs); v u(1:2:end); % 节点挠度 th u(2:2:end); % 节点转角 % 解析解用于验证 x_fine linspace(0, L, 201); v_exact q * x_fine.^2 .* (6*L^2 - 4*L*x_fine x_fine.^2) / (24*E*I); fprintf(自由端 FEM 挠度 : %.6f mm\n, v(end)*1000); fprintf(自由端解析解 : %.6f mm\n, v_exact(end)*1000);运行要点nEl 取 8 时自由端挠度已经有 4 位有效数字。解析解取均布载荷悬臂梁端部公式 v(L) qL⁴/(8EI)快速自检时可以用这条公式心算数量级。4. 验证与误差分析用解析解检验代码是否写对4.1 解析解对照公式与误差定义悬臂梁均布载荷 q 作用下距离固定端 x 处的挠度为 v(x) qx²(6L² - 4Lx x²)/(24EI)端部特例 v(L) qL⁴/(8EI)。另一类常用算例是自由端受集中力 P解为 v(L) PL³/(3EI)、θ(L) PL²/(2EI)。验证时建议同时测这两组集中力直接加在节点自由度载荷向量构造简单均布载荷则检验一致载荷向量是否写对。定义相对误差为 err |v_FEM(L) - v_exact(L)| / |v_exact(L)|这个量在细网格下应当随单元数增加单调下降。4.2 网格收敛性测试算到收敛阶就不再需要怀疑代码找收敛阶比看单一误差更有说服力。做法是分别用 1、2、4、8、16、32 个单元跑同一问题记录自由端挠度误差再用相邻网格的误差比算收敛阶。对 Hermite 梁单元理论上自由端挠度以 O(Le⁴) 收敛即加密一倍误差应缩小为约 1/16log-log 曲线的斜率接近 4。接着给出扫网格的脚本。nElList [1, 2, 4, 8, 16, 32]; err zeros(size(nElList)); for i 1:numel(nElList) v_end solveBeam(E, I, L, q, nElList(i)); err(i) abs(v_end - q*L^4/(8*E*I)) / abs(q*L^4/(8*E*I)); end order -log(err(2:end) ./ err(1:end-1)) ./ log(nElList(2:end) ./ nElList(1:end-1));这里的收敛阶是相邻两次网格加密之后计算出来的局部斜率。若代码无误order 数值会很快逼近 4若组装索引写错误差曲线会不收敛或在某个网格密度卡住。自由端集中力算例的载荷施加点恰在节点时Hermite 单元能精确满足节点条件误差几乎为零因此更适合检查边界条件是否约束住刚体自由度不适合用来检验网格收敛行为。4.3 三个高频坑奇异矩阵、符号约定、单位复核实际编写中K 矩阵“接近奇异”几乎总是由两个原因引起忘加固定端约束或者约束自由度设置成了 [1] 而不是 [1 2]。只约束挠度时梁仍可绕固定端转动方程组在数学上仍奇异MATLAB 的\会给出 NaN 或巨大的数值结果。符号约定问题更隐蔽均布载荷向下时有些代码习惯把“下”定义成正方向于是整个载荷向量符号体系翻转端部挠度结果本身仍对称但若之后要恢复弯矩内力的符号会与材料力学常用约定相反。最后强制建议在程序开头打印 EI 与 qL⁴/(8EI) 的数量级如果自由端挠度输出是 10^-6 而不是 10^-3 量级先查自己的单位不要先怀疑矩阵组错。5. 进阶技巧从位移恢复弯矩图与批量参数扫描5.1 恢复单元内力矩不要在节点处直接取弯矩位移解是有限元直接输出但工程报告通常还需要弯矩图。常见做法是取单元内部一个点计算 EI·v避免在单元边界处出现不连续。均匀网格下最简单的恢复办法是用单元两端的转角和挠度直接计算单元中点弯矩。对 Hermite 单元二阶导在单元内线性变化取 ξ0.5 时表达式为M_mid EI * (6(v1 - v2)/Le² (θ1 θ2)/Le)符号按前面约定的“挠度向上为正”来。数值验证时可直接对比均布载荷下的解析弯矩 M(x) -q(L-x)²/2。若结果在中部吻合而固定端附近偏差偏大是粗网格解的弯矩不连续造成的加密网格后该现象消失。M_mid zeros(nEl, 1); for e 1:nEl n1 e; n2 e 1; Le x(n2) - x(n1); d2v 6*(v(n1) - v(n2))/Le^2 (th(n1) th(n2))/Le; M_mid(e) E*I*d2v; end这段代码与直接提取节点弯矩相比避开了单元交界面处内力突变带来的锯齿。绘图时将 M_mid 画在单元中点并用stairs或分段直线连接就能得到一张平滑的弯矩分布图。5.2 封装求解函数做多工况批量扫描到这里脚本已能解决单工况继续优化一下复用性把“输入 E, I, L, q, nEl → 输出自由端挠度”封装成函数 solveBeam再用 MATLAB 结构体打包一组截面尺寸做参数扫描。例如要比较梁高 h 从 40mm 到 100mm 变化时端部挠度只需循环调用。这种封装一旦成型换个载荷类型或改变约束条件改动的只是载荷向量和约束自由度两行代码。扫参时注意把 nEl 设成够用且固定的值避免网格变化和物理变化混在同一张图里。这套实现没有任何工具箱依赖从单元刚度矩阵到弯矩恢复全部可读、可改非常适合继续往变截面梁、温度载荷和材料非线性方向扩展。下一处要修改的往往是单元刚度矩阵的积分过程而不是整个求解框架。本文还有配套的精品资源点击获取