MATLAB有限元分析程序的核心是将连续区域离散为简单单元、建立单元方程、组装总体系统、处理边界条件并求解。
MATLAB有限元框架程序
matlab
%% 主程序:有限元分析框架
% 解决一维杆件或梁的静力学问题
clear all; clc; close all;
% ========== 1. 定义问题参数 ==========
E = 2.0e11; % 弹性模量 (Pa)
A = 0.01; % 横截面积 (m²)
L = 1.0; % 杆件长度 (m)
num_elements = 10; % 单元数量
num_nodes = num_elements + 1; % 节点数量
% ========== 2. 节点坐标和连接矩阵 ==========
% 节点坐标 (均匀分布)
node_coords = linspace(0, L, num_nodes)';
% 单元连接关系 (每个单元连接哪两个节点)
element_nodes = zeros(num_elements, 2);
for e = 1:num_elements
element_nodes(e, :) = [e, e+1];
end
% ========== 3. 初始化全局矩阵 ==========
K_global = zeros(num_nodes); % 全局刚度矩阵
F_global = zeros(num_nodes, 1); % 全局载荷向量
% ========== 4. 计算并组装单元矩阵 ==========
for e = 1:num_elements
% 获取当前单元的节点编号
node1 = element_nodes(e, 1);
node2 = element_nodes(e, 2);
% 计算单元长度
x1 = node_coords(node1);
x2 = node_coords(node2);
le = x2 - x1; % 单元长度
% 计算单元刚度矩阵 (一维杆单元)
ke = (E*A/le) * [1, -1; -1, 1];
% 计算单元载荷向量 (假设均匀分布载荷q)
q = 1000; % 分布载荷大小 (N/m)
fe = (q*le/2) * [1; 1];
% 将单元矩阵组装到全局矩阵
indices = [node1, node2];
K_global(indices, indices) = K_global(indices, indices) + ke;
F_global(indices) = F_global(indices) + fe;
end
% ========== 5. 施加边界条件 ==========
% 固定左端 (节点1),右端自由
fixed_dof = 1; % 固定自由度
free_dofs = 2:num_nodes; % 自由自由度
% 简化刚度矩阵和载荷向量 (消除固定自由度)
K_reduced = K_global(free_dofs, free_dofs);
F_reduced = F_global(free_dofs);
% 减去已知位移的影响 (对于非零位移情况)
% 本例中固定端位移为0,所以无需处理
% ========== 6. 求解线性系统 ==========
U_reduced = K_reduced \ F_reduced;
% ========== 7. 组合完整位移向量 ==========
U = zeros(num_nodes, 1);
U(free_dofs) = U_reduced;
% ========== 8. 计算单元应力和应变 ==========
stress = zeros(num_elements, 1);
strain = zeros(num_elements, 1);
for e = 1:num_elements
node1 = element_nodes(e, 1);
node2 = element_nodes(e, 2);
le = node_coords(node2) - node_coords(node1);
% 单元位移
u1 = U(node1);
u2 = U(node2);
% 计算应变和应力
strain(e) = (u2 - u1) / le;
stress(e) = E * strain(e);
end
% ========== 9. 可视化结果 ==========
figure('Position', [100, 100, 1200, 400]);
% 子图1: 位移分布
subplot(1, 3, 1);
plot(node_coords, U, 'b-o', 'LineWidth', 2, 'MarkerSize', 8);
xlabel('位置 (m)'); ylabel('位移 (m)');
title('节点位移分布'); grid on;
% 子图2: 应力分布
subplot(1, 3, 2);
element_centers = (node_coords(1:end-1) + node_coords(2:end)) / 2;
bar(element_centers, stress/1e6, 'FaceColor', [0.8, 0.2, 0.2]);
xlabel('位置 (m)'); ylabel('应力 (MPa)');
title('单元应力分布'); grid on;
% 子图3: 变形前后的对比
subplot(1, 3, 3);
scale_factor = 1000; % 位移放大系数,便于观察
hold on;
% 绘制原始形状
plot(node_coords, zeros(size(node_coords)), 'k--', 'LineWidth', 1);
% 绘制变形后的形状
plot(node_coords, scale_factor * U, 'r-', 'LineWidth', 2);
scatter(node_coords, scale_factor * U, 50, 'filled', 'r');
xlabel('位置 (m)'); ylabel('位移 (放大后)');
title('变形前后对比');
legend('原始形状', '变形后形状', 'Location', 'best');
grid on; hold off;
% ========== 10. 输出关键结果 ==========
fprintf('========== 有限元分析结果 ==========\n');
fprintf('节点总数: %d\n', num_nodes);
fprintf('单元总数: %d\n', num_elements);
fprintf('最大位移: %.6e m (位于节点 %d)\n', max(abs(U)), find(abs(U)==max(abs(U))));
fprintf('最大应力: %.2f MPa\n', max(abs(stress))/1e6);
fprintf('最小应力: %.2f MPa\n', min(abs(stress))/1e6);
关键函数库(需单独保存为.m文件)
以下是上述主程序依赖的核心函数:
matlab
%% 文件1: BeamElementStiffness.m - 计算梁单元刚度矩阵
function [ke] = BeamElementStiffness(E, I, L)
% 计算欧拉梁单元刚度矩阵
% 输入: E - 弹性模量, I - 截面惯性矩, L - 单元长度
% 输出: ke - 4x4单元刚度矩阵
ke = (E*I/L^3) * [12, 6*L, -12, 6*L;
6*L, 4*L^2, -6*L, 2*L^2;
-12, -6*L, 12, -6*L;
6*L, 2*L^2, -6*L, 4*L^2];
end
matlab
%% 文件2: BeamAssemble.m - 组装全局刚度矩阵
function [K] = BeamAssemble(K, ke, element_nodes)
% 将单元刚度矩阵组装到全局刚度矩阵
% 输入: K - 全局刚度矩阵, ke - 单元刚度矩阵,
% element_nodes - 单元的节点连接关系
% 输出: K - 组装后的全局刚度矩阵
for i = 1:size(ke, 1)
for j = 1:size(ke, 2)
% 将单元矩阵的每个元素加到全局矩阵的对应位置
K(element_nodes(i), element_nodes(j)) = ...
K(element_nodes(i), element_nodes(j)) + ke(i, j);
end
end
end
matlab
%% 文件3: ApplyBoundaryConditions.m - 施加边界条件
function [K_reduced, F_reduced] = ApplyBoundaryConditions(K, F, fixed_dofs)
% 处理边界条件(固定自由度)
% 输入: K - 全局刚度矩阵, F - 全局载荷向量,
% fixed_dofs - 固定的自由度编号
% 输出: K_reduced, F_reduced - 处理后的矩阵和向量
num_dofs = size(K, 1);
free_dofs = setdiff(1:num_dofs, fixed_dofs);
% 提取子矩阵
K_reduced = K(free_dofs, free_dofs);
F_reduced = F(free_dofs);
% 如果固定端位移不为零,需要修改载荷项
% F_reduced = F_reduced - K(free_dofs, fixed_dofs) * prescribed_displacements;
end
参考代码 matlab 有限元源程序 www.youwenfan.com/contentcsp/23370.html
有限元分析完整流程图
MATLAB有限元程序的标准工作流程
开始:问题定义
材料属性、几何尺寸
离散化:网格划分
生成节点与单元
单元分析
计算单元刚度矩阵与载荷
整体组装
形成全局刚度矩阵与载荷向量
边界条件处理
施加约束与载荷
求解线性系统
Ku=F
后处理
计算应力应变等
结果可视化
位移、应力云图
不同问题的有限元代码扩展
1. 二维三角形单元(热传导问题)
matlab
function [ke] = TriElementStiffness(k, nodes)
% 计算三角形单元的热传导矩阵
% nodes: 3x2矩阵,包含三个节点的(x,y)坐标
x = nodes(:,1); y = nodes(:,2);
% 计算三角形面积
A = 0.5 * abs((x(2)-x(1))*(y(3)-y(1)) - (x(3)-x(1))*(y(2)-y(1)));
% 形状函数导数
b = [y(2)-y(3); y(3)-y(1); y(1)-y(2)];
c = [x(3)-x(2); x(1)-x(3); x(2)-x(1)];
% 单元刚度矩阵
ke = (k/(4*A)) * [b(1)^2+c(1)^2, b(1)*b(2)+c(1)*c(2), b(1)*b(3)+c(1)*c(3);
b(2)*b(1)+c(2)*c(1), b(2)^2+c(2)^2, b(2)*b(3)+c(2)*c(3);
b(3)*b(1)+c(3)*c(1), b(3)*b(2)+c(3)*c(2), b(3)^2+c(3)^2];
end
2. 动态分析(质量矩阵)
matlab
function [me] = BeamElementMass(rho, A, L)
% 计算梁单元一致质量矩阵
me = (rho*A*L/420) * [156, 22*L, 54, -13*L;
22*L, 4*L^2, 13*L, -3*L^2;
54, 13*L, 156, -22*L;
-13*L, -3*L^2, -22*L, 4*L^2];
end
% 特征值分析(模态分析)
M_global = ... % 全局质量矩阵(组装方式同刚度矩阵)
K_global = ... % 全局刚度矩阵
% 求解广义特征值问题: K*φ = ω²*M*φ
[V, D] = eig(K_global, M_global);
frequencies = sqrt(diag(D))/(2*pi); % 转换为Hz
使用建议与调试技巧
-
从简单开始:先用1-2个单元验证程序正确性,再增加网格密度。
-
验证结果:
- 检查对称性:刚度矩阵应对称正定
- 刚性位移:无约束结构应有零特征值
- 与解析解对比:如简支梁中点挠度 ( \delta = \frac{PL^3}{48EI} )
-
常见错误处理:
matlab
% 1. 矩阵奇异(刚度矩阵不可逆)
% 原因:约束不足,存在刚体位移
% 解决:检查并施加足够的边界条件
% 2. 收敛问题
% 原因:网格太粗或单元类型不合适
% 解决:细化网格或使用高阶单元
% 3. 结果不物理
% 原因:材料参数错误或载荷方向错误
% 解决:检查输入参数的单位和量纲
- 性能优化:
matlab
% 使用稀疏矩阵存储(对于大规模问题)
K_sparse = sparse(num_dofs, num_dofs);
% 在组装时使用稀疏矩阵操作
% 并行计算(Parfor循环)
parfor e = 1:num_elements
% 并行计算单元矩阵
end
这个框架覆盖了有限元分析的核心流程。你可以通过替换单元刚度矩阵函数 来适应不同问题(杆、梁、板、壳、三维实体),通过修改边界条件处理函数 来适应各种约束类型,通过扩展求解器来进行静力、动力、线性或非线性分析。