为什么约束 3 个自由度后无法求解实体有限元问题?

计算科学 有限元 matlab 固体力学
2021-12-02 12:46:37

我编写了一个简单的 MATLAB 代码来解决固体 FEM 问题。

问题看起来像这样

(1)      (2)
x-------x
|     / |
|   /   |
| /     |
x-------x
(3)     (4)

每个节点有两个自由度(DOF),代表xy位移。

边界条件

node 1只想要约束x,yDOF 和node 2's $x DOF,即将 DOF 约束1,2,3为零。

负载条件

所有节点的节点力都等于 1。

结果

我发现全局刚度矩阵的秩是 7 而不是 8,导致问题无法解决。

问题

在 2D 实体 FEM 情况下,需要约束 3 个自由度以限制刚体沿x,y轴和旋转。但是我约束了3个自由度后,问题仍然无法解决。为什么?

附录

matlab代码看起来像

clc
clear
close all
%% model
x_range=10;
y_range=10;
num_x_node=2;
num_y_node=2;
num_node=num_x_node*num_y_node;
DOF=2;
%% generate grid
node_coordinate_table=calculateNodeCoordinateTableForRectangleDomain(num_x_node,num_y_node,x_range,y_range);
element_node_table=calculateElementNodeTableForRectangleDomainTriangleGrid(num_x_node,num_y_node);
%% calculate element matrix
K=calcGlobalMatrix(node_coordinate_table,element_node_table,DOF);
%% load
P=ones(num_node*DOF,1);
%% constrain
is_fix_dof=zeros(num_node*DOF,1);
is_fix_dof(1)=1;
is_fix_dof(2)=1;
is_fix_dof(3)=1;
%% modify discrete equation by constrain (cross zero center one method)
for i=1:1:num_node*DOF
    if is_fix_dof(i)==1
        K(i,:)=0;
        K(:,i)=0;
        K(i,i)=1;
        P(i)=0;
    end
end
%% solution
x=K\P
%% plot grid
figure
set(gcf,'position',[50,50,1000,800])
hold on
plotNode(node_coordinate_table);
plotElement(element_node_table,node_coordinate_table);

%% function
function K=calcGlobalMatrix(node_coordinate_table,element_node_table,DOF)
num_node=size(node_coordinate_table,1);
K=zeros(DOF*num_node);
element_matrix_array=calculateElementMatrixArray(node_coordinate_table,element_node_table);
num_element=size(element_node_table,1);
for i=1:1:num_element
    K0=element_matrix_array{i};
    node_global_index_array=element_node_table(i,:);
    for node_i=1:1:3
        for node_j=1:1:3
            for i1=1:1:DOF
                for j1=1:1:DOF
                    node_global_index_i=node_global_index_array(node_i);
                    node_global_index_j=node_global_index_array(node_j);
                    row=(node_i-1)*DOF+i1;
                    col=(node_j-1)*DOF+j1;
                    ROW=(node_global_index_i-1)*DOF+i1;
                    COL=(node_global_index_j-1)*DOF+j1;
                    K(ROW,COL)=K(ROW,COL)+K0(row,col);
                end
            end
        end
    end
end

end

function [element_matrix_array]=calculateElementMatrixArray(node_coordinate_table,element_node_table)
num_element=size(element_node_table,1);
element_matrix_array=cell(num_element,1);
for i=1:1:num_element
    node_a_id=element_node_table(i,1);
    node_b_id=element_node_table(i,2);
    node_c_id=element_node_table(i,3);
    x=zeros(3,1);
    x(1)=node_coordinate_table(node_a_id,1);
    x(2)=node_coordinate_table(node_b_id,1);
    x(3)=node_coordinate_table(node_c_id,1);
    y=zeros(3,1);
    y(1)=node_coordinate_table(node_a_id,2);
    y(2)=node_coordinate_table(node_b_id,2);
    y(3)=node_coordinate_table(node_c_id,2);
    element_matrix_array{i}=calculateElementMatrixByNodeCoordinate(x,y);
end

end

function plotNode(node_coordinate_table)
x=node_coordinate_table(:,1);
y=node_coordinate_table(:,2);
plot(x,y,'o');
num_node=size(node_coordinate_table,1);
for i=1:1:num_node
    node_x=x(i);
    node_y=y(i);
    text(node_x,node_y,num2str(i));
end

end

function plotElement(element_node_table,node_coordinate)
num_element=size(element_node_table,1);
for i=1:1:num_element
    node_a_id=element_node_table(i,1);
    node_b_id=element_node_table(i,2);
    node_c_id=element_node_table(i,3);
    x_a=node_coordinate(node_a_id,1);
    y_a=node_coordinate(node_a_id,2);
    x_b=node_coordinate(node_b_id,1);
    y_b=node_coordinate(node_b_id,2);
    x_c=node_coordinate(node_c_id,1);
    y_c=node_coordinate(node_c_id,2);
    plot([x_a,x_b,x_c,x_a],[y_a,y_b,y_c,y_a],'k-');
    x_o=(x_a+x_b+x_c)/3;
    y_o=(y_a+y_b+y_c)/3;
    text(x_o,y_o,[num2str(i)]);% -1 for plot element index
end
end

function node_coordinate_table=calculateNodeCoordinateTableForRectangleDomain(num_x_node,num_y_node,x_range,y_range)
num_node=num_x_node*num_y_node;
num_x_element=num_x_node-1;
num_y_element=num_y_node-1;
node_coordinate_table=zeros(num_node,2);
n=1;
dx=x_range/num_x_element;
dy=y_range/num_y_element;
for j=1:1:num_y_node
    for i=1:1:num_x_node
        x = (i-1) * dx;
        y = y_range - (j-1) * dy;
        node_coordinate_table(n,1)=x;
        node_coordinate_table(n,2)=y;
        n=n+1;
    end
end
end

function element_node_table=calculateElementNodeTableForRectangleDomainTriangleGrid(num_x_node,num_y_node)
% element node table generate is order in matlab format, that is, id start from 1
num_x_element=num_x_node-1;
num_y_element=num_y_node-1;
num_element=num_x_element*num_y_element*2;
element_node_table = zeros(num_element,3);
n=1;
for j=1:1:num_y_element
    for i=1:1:num_x_element
        %  a--c
        %  | /|
        %  |/ |
        %  b--d
        node_a_id=i+(j-1)*num_x_node;
        node_b_id=node_a_id+num_x_node;
        node_c_id=node_a_id+1;
        node_d_id=node_b_id+1;
        % upper element abc
        element_node_table(n,1)=node_a_id;
        element_node_table(n,2)=node_b_id;
        element_node_table(n,3)=node_c_id;
        n=n+1;
        % lower element cbd
        element_node_table(n,1)=node_c_id;
        element_node_table(n,2)=node_b_id;
        element_node_table(n,3)=node_d_id;
        n=n+1;
    end
end
end

function K0=calculateElementMatrixByNodeCoordinate(x,y)
% reference
% finite element method, wang xucheng chapter 2

% model
E_0=100;
nu_0=0;
Thickness=1;
% calculate element matrix
a=zeros(3,1);
b=zeros(3,1);
c=zeros(3,1);
for i=1:1:3
    if(i==1);j=2;m=3;end
    if(i==2);j=3;m=1;end
    if(i==3);j=1;m=2;end
    a(i)=x(j)*y(m)-x(m)*y(j);
    b(i)=y(j)-y(m);
    c(i)=-x(j)+x(m);
end
A=1/2*(b(i)*c(j)-b(j)*c(i));
K0=zeros(6,6);
for r=1:1:3
    for s=1:1:3
        K0(2*r-1,2*s-1)=b(r)*b(s)+(1-nu_0)/2*c(r)*c(s);
        K0(2*r-1,2*s)=nu_0*b(r)*c(s)+(1-nu_0)/2*c(r)*b(s);
        K0(2*r,2*s-1)=nu_0*c(r)*b(s)+(1-nu_0)/2*b(r)*c(s);
        K0(2*r,2*s)=c(r)*c(s)+(1-nu_0)/2*b(r)*b(s);
    end
end
K0=K0*E_0*Thickness/(4*A*(1-nu_0^2));
end
```
1个回答

您选择的特定约束集不会阻止刚体围绕节点 1 旋转。因此,正如您所指出的,刚度矩阵是奇异的。防止这种刚体旋转的一种方法是将节点 2 处的 y 位移设置为零。您还可以在节点 3 或节点 4 处约束 x 位移以防止旋转。

看到这一点的一种方法是将约束替换为与约束作用方向相同的反作用力。防止主体围绕节点 1 旋转需要由于约束而产生的反作用力围绕节点 1 产生扭矩。节点 2 处的 x 方向上的反作用力不产生扭矩。