MATLAB实现梁单元刚度矩阵的计算和总体刚度矩阵的组装

1. 理论核心:梁单元刚度矩阵

1.1 局部坐标系下的梁单元刚度矩阵

对于平面梁单元(每个节点有3个自由度:u, v, θ),在局部坐标系下的刚度矩阵为:

局部坐标系下的刚度矩阵公式:

k_local = [EA/L,      0,           0,      -EA/L,      0,           0;
            0,     12EI/L³,   6EI/L²,        0,   -12EI/L³,   6EI/L²;
            0,     6EI/L²,    4EI/L,         0,   -6EI/L²,    2EI/L;
          -EA/L,      0,           0,       EA/L,      0,           0;
            0,    -12EI/L³,  -6EI/L²,        0,    12EI/L³,  -6EI/L²;
            0,     6EI/L²,    2EI/L,         0,   -6EI/L²,    4EI/L]

其中:

  • E = 弹性模量
  • A = 横截面积
  • I = 截面惯性矩
  • L = 单元长度

1.2 坐标变换:局部→全局

这是最关键的一步。实际结构中梁单元方向各异,需要将局部坐标系的刚度矩阵转换到全局坐标系:

坐标转换公式:

k_global = Tᵀ * k_local * T

其中变换矩阵 T 为:

T = [cosβ,  sinβ,  0,    0,     0,     0;
    -sinβ,  cosβ,  0,    0,     0,     0;
       0,     0,   1,    0,     0,     0;
       0,     0,   0,  cosβ,  sinβ,    0;
       0,     0,   0, -sinβ,  cosβ,    0;
       0,     0,   0,    0,     0,     1]

β 是梁单元与全局X轴的夹角。

2. MATLAB实现代码

2.1 主程序框架

% 有限元分析:梁结构总体刚度矩阵组装
clear; clc; close all;

%% 1. 输入参数
E = 2.1e11;      % 弹性模量 (Pa, 钢)
A = 0.01;        % 截面积 (m²)
I = 8.33e-6;     % 惯性矩 (m⁴)

% 节点坐标 (x, y) [单位: m]
nodes = [0, 0;     % 节点1
         2, 0;     % 节点2  
         4, 0;     % 节点3
         2, 2];    % 节点4

% 单元连接关系 [起始节点, 终止节点]
elements = [1, 2;   % 单元1
            2, 3;   % 单元2
            2, 4;   % 单元3
            3, 4];  % 单元4

num_nodes = size(nodes, 1);     % 节点总数
num_elements = size(elements, 1); % 单元总数
dof_per_node = 3;               % 每个节点的自由度
total_dof = num_nodes * dof_per_node; % 总自由度

%% 2. 初始化总体刚度矩阵
K_global = zeros(total_dof, total_dof);

%% 3. 循环处理每个单元
for e = 1:num_elements
    % 3.1 获取单元信息
    node1 = elements(e, 1);
    node2 = elements(e, 2);
    
    % 节点坐标
    x1 = nodes(node1, 1); y1 = nodes(node1, 2);
    x2 = nodes(node2, 1); y2 = nodes(node2, 2);
    
    % 3.2 计算单元长度和角度
    L = sqrt((x2 - x1)^2 + (y2 - y1)^2);  % 单元长度
    cos_beta = (x2 - x1) / L;             % 方向余弦
    sin_beta = (y2 - y1) / L;             % 方向正弦
    
    % 3.3 计算局部刚度矩阵
    k_local = beamLocalStiffness(E, A, I, L);
    
    % 3.4 计算变换矩阵
    T = transformationMatrix(cos_beta, sin_beta);
    
    % 3.5 转换到全局坐标系
    k_global_element = T' * k_local * T;
    
    % 3.6 组装到总体刚度矩阵
    K_global = assembleGlobalStiffness(K_global, k_global_element, ...
                                       node1, node2, dof_per_node);
end

%% 4. 输出结果
fprintf('=== 梁结构有限元分析结果 ===\n');
fprintf('节点数: %d\n', num_nodes);
fprintf('单元数: %d\n', num_elements);
fprintf('总自由度: %d\n', total_dof);
fprintf('总体刚度矩阵维度: %d × %d\n', size(K_global));

% 显示总体刚度矩阵(部分)
disp('总体刚度矩阵(前12×12部分):');
disp(K_global(1:min(12,total_dof), 1:min(12,total_dof)));

2.2 核心函数:梁单元局部刚度矩阵

function k_local = beamLocalStiffness(E, A, I, L)
% 计算局部坐标系下的梁单元刚度矩阵
% 输入: E-弹性模量, A-截面积, I-惯性矩, L-单元长度
% 输出: 6×6局部刚度矩阵

% 预计算常用项
EA_L = E * A / L;
EI_L3 = 12 * E * I / L^3;
EI_L2 = 6 * E * I / L^2;
EI_L = 4 * E * I / L;
EI_L_half = 2 * E * I / L;

% 组装局部刚度矩阵
k_local = zeros(6, 6);

% 第一行
k_local(1,1) = EA_L;   k_local(1,4) = -EA_L;

% 第二行  
k_local(2,2) = EI_L3;  k_local(2,3) = EI_L2;
k_local(2,5) = -EI_L3; k_local(2,6) = EI_L2;

% 第三行
k_local(3,2) = EI_L2;  k_local(3,3) = EI_L;
k_local(3,5) = -EI_L2; k_local(3,6) = EI_L_half;

% 第四行 (对称于第一行)
k_local(4,1) = -EA_L;  k_local(4,4) = EA_L;

% 第五行 (对称于第二行)
k_local(5,2) = -EI_L3; k_local(5,3) = -EI_L2;
k_local(5,5) = EI_L3;  k_local(5,6) = -EI_L2;

% 第六行 (对称于第三行)
k_local(6,2) = EI_L2;  k_local(6,3) = EI_L_half;
k_local(6,5) = -EI_L2; k_local(6,6) = EI_L;

% 利用对称性填充上三角部分
for i = 1:6
    for j = i+1:6
        k_local(i,j) = k_local(j,i);
    end
end
end

2.3 核心函数:坐标变换矩阵

function T = transformationMatrix(cos_beta, sin_beta)
% 计算局部到全局坐标的变换矩阵
% 输入: cos_beta-方向余弦, sin_beta-方向正弦
% 输出: 6×6变换矩阵

T = zeros(6, 6);

% 变换矩阵的各个子块
T_sub = [cos_beta, sin_beta, 0;
        -sin_beta, cos_beta, 0;
          0,          0,     1];

% 填充变换矩阵
T(1:3, 1:3) = T_sub;
T(4:6, 4:6) = T_sub;
end

2.4 核心函数:总体刚度矩阵组装

function K_global = assembleGlobalStiffness(K_global, k_element, ...
                                           node1, node2, dof_per_node)
% 将单元刚度矩阵组装到总体刚度矩阵
% 输入: K_global-当前总体矩阵, k_element-单元矩阵
%       node1, node2-节点编号, dof_per_node-每节点自由度
% 输出: 更新后的总体刚度矩阵

% 计算在总体矩阵中的位置索引
dof_index1 = (node1-1)*dof_per_node + (1:dof_per_node);
dof_index2 = (node2-1)*dof_per_node + (1:dof_per_node);

% 所有相关自由度索引
dof_indices = [dof_index1, dof_index2];

% 组装过程 (直接加和法)
for i = 1:length(dof_indices)
    row_global = dof_indices(i);
    for j = 1:length(dof_indices)
        col_global = dof_indices(j);
        % 将单元矩阵的贡献加到总体矩阵
        K_global(row_global, col_global) = ...
            K_global(row_global, col_global) + k_element(i, j);
    end
end
end

3. 结果验证与调试方法

3.1 验证总体刚度矩阵的特性

组装完成后,务必检查以下数学特性:

%% 验证总体刚度矩阵的特性
fprintf('\n=== 矩阵特性验证 ===\n');

% 1. 对称性检查
sym_error = max(max(abs(K_global - K_global')));
fprintf('对称性误差: %.2e (应接近0)\n', sym_error);

% 2. 半正定性检查(无约束时应有零特征值)
eigenvalues = eig(K_global);
fprintf('最小特征值: %.2e\n', min(eigenvalues));
fprintf('零特征值个数: %d (刚体模态)\n', sum(abs(eigenvalues) < 1e-9));

% 3. 对角线元素检查(应全为正,边界条件处理前)
diag_elements = diag(K_global);
fprintf('对角线元素最小值: %.2e\n', min(diag_elements));
fprintf('对角线元素最大值: %.2e\n', max(diag_elements));

3.2 可视化函数(可选但推荐)

function plotBeamStructure(nodes, elements, K_global)
% 可视化梁结构和刚度矩阵模式
figure('Position', [100, 100, 1200, 500]);

% 子图1:结构几何
subplot(1,2,1);
hold on; grid on; axis equal;
title('梁结构几何', 'FontSize', 12);

% 绘制单元
for e = 1:size(elements, 1)
    node1 = elements(e, 1);
    node2 = elements(e, 2);
    plot([nodes(node1,1), nodes(node2,1)], ...
         [nodes(node1,2), nodes(node2,2)], ...
         'b-o', 'LineWidth', 2, 'MarkerSize', 8, ...
         'MarkerFaceColor', 'r');
end

% 标注节点编号
for i = 1:size(nodes, 1)
    text(nodes(i,1)+0.1, nodes(i,2)+0.1, ...
         sprintf('%d', i), 'FontSize', 12, 'Color', 'k');
end
xlabel('X (m)'); ylabel('Y (m)');

% 子图2:刚度矩阵稀疏模式
subplot(1,2,2);
spy(K_global, 'b.', 10);
title('总体刚度矩阵稀疏模式', 'FontSize', 12);
xlabel('自由度编号'); ylabel('自由度编号');

% 添加矩阵信息
matrix_info = sprintf('维度: %d×%d\n非零元素: %d\n稀疏度: %.2f%%', ...
                     size(K_global,1), size(K_global,2), ...
                     nnz(K_global), 100*nnz(K_global)/numel(K_global));
text(0.05, 0.95, matrix_info, 'Units', 'normalized', ...
     'FontSize', 10, 'BackgroundColor', 'w');
end

参考代码 利用MATLAB计算梁单元刚度矩阵,并组装成总体刚度矩阵 www.3dddown.com/cnb/54607.html

4. 使用示例与扩展建议

4.1 运行示例

% 在主程序末尾调用可视化函数
plotBeamStructure(nodes, elements, K_global);

% 保存结果
save('beam_analysis_results.mat', 'K_global', 'nodes', 'elements', 'E', 'A', 'I');

4.2 扩展功能建议

  1. 添加边界条件处理:在组装后引入约束,消除刚体位移
  2. 载荷向量组装:添加集中力、分布载荷的处理
  3. 求解位移和内力:扩展求解功能 U = K\F
  4. 支持三维梁单元:扩展为每节点6自由度的空间梁
  5. 材料非线性:引入非线性本构关系
  6. 动态分析:添加质量矩阵形成特征值问题

4.3 常见问题排查

  • 矩阵奇异性:施加约束前总体刚度矩阵必然奇异(有刚体模态)
  • 数值精度:使用双精度运算,避免大数吃小数
  • 内存优化:对于大规模问题,使用稀疏矩阵存储 K_sparse = sparse(K_global)
posted @ 2026-02-03 14:02  yes_go  阅读(177)  评论(0)    收藏  举报