⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exam5_1.m

📁 这个压缩包是浙江大学徐荣桥主编的<<结构分析有限元与Matlab程序设计>>一书各章的源代码!
💻 M
字号:
function exam5_1
% 本程序为第五章的第一个算例,采用四面体单元计算单向拉伸杆的横截面应力
%  输入参数: 
%      无

% 定义全局变量
%      gNode ------ 节点坐标
%      gElement --- 单元定义
%      gMaterial -- 材料性质
%      gBC1 ------- 第一类约束条件
%      gDF -------- 分布力
%      gNF -------- 集中力
%      gK --------- 整体刚度矩阵
%      gDelta ----- 整体节点坐标

    file_in = 'exam5_1.dat' ;
    
    % 检查文件是否存在
    if exist( file_in ) == 0
        disp( sprintf( '错误:文件 %s 不存在', file_in ) )
        disp( sprintf( '程序终止' ) )
        return ;
    end
    
    % 根据输入文件名称生成输出文件名称
    [path_str,name_str,ext_str] = fileparts( file_in ) ;
    ext_str_out = '.mat' ;
    file_out = fullfile( path_str, [name_str, ext_str_out] ) ;
    
    % 检查输出文件是否存在
    if exist( file_out ) ~= 0 
        answer = input( sprintf( '文件 %s 已经存在,是否覆盖? ( Yes / [No] ):  ', file_out ), 's' ) ;
        if length( answer ) == 0
            answer = 'no' ;
        end
        
        answer = lower( answer ) ;
        if answer ~= 'y' | answer ~= 'yes' 
            disp( sprintf( '请使用另外的文件名,或备份已有的文件' ) ) ;
            disp( sprintf( '程序终止' ) );
            return ; 
        end
    end


    FemModel( file_in ) ;       % 定义有限元模型
    SolveModel ;                % 求解有限元模型
    SaveResults( file_out ) ;   % 保存计算结果
    DisplayResults(file_out) ;  % 显示结果
return ;

function FemModel( file_in )
%  定义有限元模型
%  输入参数:
%      file_in --- 输入文件名称
%  返回值:
%  说明:
    global gNode gElement gMaterial gBC1 gDF gNF
    
    % 打开文件
    fid = fopen( file_in, 'r' ) ;
    
    % 节点坐标
    node_number = fscanf( fid, '%d', 1 ) ;
    gNode = zeros( node_number, 3 ) ;
    for i = 1:node_number
        dummy = fscanf( fid, '%d', 1 ) ;
        gNode( i, : ) = fscanf( fid, '%f', [1 3] ) ;
    end
    
    % 单元定义
    element_number = fscanf( fid, '%d', 1 ) ;
    gElement = zeros( element_number, 5 ) ;
    for i = 1:element_number
        dummy = fscanf( fid, '%d', 1 ) ;
        gElement( i, : ) = fscanf( fid, '%d', [1 5] ) ;
    end
    
    % 材料性质
    material_number = fscanf( fid, '%d', 1 ) ;
    gMaterial = zeros( material_number, 2 ) ;
    for i = 1:material_number
        dummy = fscanf( fid, '%d', 1 ) ;
        gMaterial( i, : ) = fscanf( fid, '%f', [1 2] ) ;
    end
    
    % 第一类约束条件
    bc1_number = fscanf( fid, '%d', 1 ) ;
    gBC1 = zeros( bc1_number, 3 ) ;
    for i=1:bc1_number
        gBC1(i,1) = fscanf( fid, '%d', 1 ) ;  % 结点号
        gBC1(i,2) = fscanf( fid, '%d', 1 ) ;  % 自由度号
        gBC1(i,3) = fscanf( fid, '%f', 1 ) ;  % 约束值
    end
    
    % 分布压力(线性分布)
    df_number = fscanf( fid, '%d', 1 ) ;
    gDF = zeros( df_number, 7 ) ;
    for i=1:df_number
        gDF(i,1:3) = fscanf( fid, '%d', [1 3] ) ;  % 三个结点号
        gDF(i,4:6) = fscanf( fid, '%f', [1 3] ) ;  % 三个结点上的压力值 
    end
    
    % 集中力
    nf_number = fscanf( fid, '%d', 1 ) ;
    gNF = zeros( nf_number, 3 ) ;
    for i=1:nf_number
        gNF(i,1) = fscanf( fid, '%d', 1 ) ;  % 结点号
        gNF(i,2) = fscanf( fid, '%d', 1 ) ;  % 自由度号
        gNF(i,3) = fscanf( fid, '%f', 1 ) ;  % 集中力大小
    end
    
    % 关闭文件
    fclose( fid ) ;
return

function SolveModel
%  求解有限元模型
%  输入参数:
%     无
%  返回值:
%     无
%  说明:
%      该函数求解有限元模型,过程如下
%        1. 计算单元刚度矩阵,集成整体刚度矩阵
%        2. 计算单元的等效节点力,集成整体节点力向量
%        3. 处理约束条件,修改整体刚度矩阵和节点力向量
%        4. 求解方程组,得到整体节点位移向量

    global gNode gElement gMaterial gBC1 gDF gNF gK gDelta gNodeStress gElementStress

    % step1. 定义整体刚度矩阵和节点力向量
    [node_number,dummy] = size( gNode ) ;
    gK = sparse( node_number * 3, node_number * 3 ) ;
    f = sparse( node_number * 3, 1 ) ;

    % step2. 计算单元刚度矩阵,并集成到整体刚度矩阵中
    [element_number,dummy] = size( gElement ) ;
    for ie=1:1:element_number
        disp( sprintf(  '计算节点刚度矩阵并集成,当前单元: %d', ie  ) ) ;
        k = StiffnessMatrix( ie ) ;
        AssembleStiffnessMatrix( ie, k ) ;
    end

    % step3. 计算分布压力的等效节点力,并集成到整体节点力向量中
    [df_number, dummy] = size( gDF ) ;
    for idf = 1:1:df_number
        enf = EquivalentDistPressure( gDF(idf,1:3), gDF(idf,4:6) ) ;
        i = gDF(idf, 1) ;
        j = gDF(idf, 2) ;
        m = gDF(idf, 3) ;
        f( (i-1)*3+1:(i-1)*3+3 ) = f( (i-1)*3+1:(i-1)*3+3 ) + enf( 1:3 ) ;
        f( (j-1)*3+1:(j-1)*3+3 ) = f( (j-1)*3+1:(j-1)*3+3 ) + enf( 4:6 ) ;
        f( (m-1)*3+1:(m-1)*3+3 ) = f( (m-1)*3+1:(m-1)*3+3 ) + enf( 7:9 ) ;
    end
  
    % step4. 把集中力集成到整体节点力向量中
    [nf_number, dummy] = size( gNF ); 
    for i = 1:1:nf_number
        in = gNF( i, 1 ) ;
        id = gNF( i, 2 ) ;
        f( (in-1)*3 + id ) = f( (in-1)*3 + id ) + gNF( i, 3 ) ;
    end
    
    % step5. 处理约束条件,修改刚度矩阵和节点力向量。采用乘大数法
    [bc_number,dummy] = size( gBC1 ) ;
    for ibc=1:1:bc_number
        n = gBC1(ibc, 1 ) ;
        d = gBC1(ibc, 2 ) ;
        m = (n-1)*3 + d ;
        f(m) = gBC1(ibc, 3)* gK(m,m) * 1e15 ;
        gK(m,m) = gK(m,m) * 1e15 ;
    end

    % step 6. 求解方程组,得到节点位移向量
    gDelta = gK \ f ;
    
    % step 6. 计算单元应力
    gElementStress = zeros( element_number, 6 ) ;
    for ie=1:element_number 
        disp( sprintf(  '计算单元应力,当前单元: %d', ie  ) ) ;
        es = ElementStress( ie ) ;
        gElementStress( ie, : ) = es ;
    end
    
    % step 7. 计算节点应力(采用绕节点加权平均)
    gNodeStress = zeros( node_number, 6 ) ;       
    for i=1:node_number                         
        disp( sprintf(  '计算节点应力,当前结点: %d', i  ) ) ;
        S = zeros( 1, 6 ) ;                         
        V = 0 ;
        for ie=1:1:element_number
            for k=1:1:4
                if i == gElement( ie, k ) 
                    vol = ElementVolume( ie ) ;
                    S = S + gElementStress(ie,:) * vol ;
                    V = V + vol ;
                    break ;
                end
            end
        end
        gNodeStress(i,:) = S / V ;
    end
return

function k = StiffnessMatrix( ie )
%  计算单元刚度矩阵
%  输入参数:
%     ie ----  单元号
%  返回值:
%     k  ----  单元刚度矩阵

    global gNode gElement gMaterial 
    
    % 读取结点坐标
    x = gNode( gElement( ie, : ), 1 ) ;
    y = gNode( gElement( ie, : ), 2 ) ;
    z = gNode( gElement( ie, : ), 3 ) ;
    
    % 计算 6V
    V6 = det( [1 x(1) y(1) z(1)
               1 x(2) y(2) z(2)
               1 x(3) y(3) z(3)
               1 x(4) y(4) z(4) ] ) ;
           
    if V6 < 0
        disp( sprintf( '警告:单元 %d 的结点排列顺序有问题', ie ) ) ;
        pause ;
    end
    % 计算应变矩阵
    B = zeros( 6, 12 ) ;
    for i=1:4
        j = mod(i,  4) + 1 ;
        m = mod(i+1,4) + 1 ;
        p = mod(i+2,4) + 1 ;
        bi = - det( [ 1 y(j) z(j)
                      1 y(m) z(m)
                      1 y(p) z(p) ] ) ;
        ci =   det( [ 1 x(j) z(j)
                      1 x(m) z(m)
                      1 x(p) z(p) ] ) ;
        di = - det( [ 1 x(j) y(j)
                      1 x(m) y(m)
                      1 x(p) y(p) ] ) ;
        B(:,(i-1)*3+1:(i-1)*3+3 ) = (-1)^(i+1)*[bi   0   0
                                                 0  ci   0
                                                 0   0  di
                                                 0  di  ci
                                                di   0  bi
                                                ci  bi   0] ;
    end
    B = B / V6 ;
    
    % 计算弹性矩阵
    E = gMaterial( gElement( ie, 5 ), 1 ) ;
    mu = gMaterial( gElement( ie, 5 ), 2 ) ;
    A1 = mu/(1-mu) ;
    A2 = (1-2*mu)/2/(1-mu) ;
    A3 = E*(1-mu)/(1+mu)/(1-2*mu) ;
    D = [  1  A1  A1   0   0   0
          A1   1  A1   0   0   0
          A1  A1   1   0   0   0
           0   0   0  A2   0   0 
           0   0   0  0   A2   0
           0   0   0  0    0  A2] ;
    D = D * A3 ;
    
    % 计算单元刚度矩阵
    V = abs(V6)/6 ;
    k = transpose( B ) * D * B * V ;
return

function AssembleStiffnessMatrix( ie, k )
%  把单元刚度矩阵集成到整体刚度矩阵
%  输入参数:
%      ie  --- 单元号
%      k   --- 单元刚度矩阵
%  返回值:
%      无
    global gElement gK
    for i=1:1:4
        for j=1:1:4
            for p=1:1:3
                for q=1:1:3
                    m = (i-1)*3+p ;
                    n = (j-1)*3+q ;
                    M = (gElement(ie,i)-1)*3+p ;
                    N = (gElement(ie,j)-1)*3+q ;
                    gK(M,N) = gK(M,N) + k(m,n) ;
                end
            end
        end
    end
return

function enf = EquivalentDistPressure( node, pressure )
%   计算线性分布压力的等效节点力
%   输入参数:
%      node ----------  结点号
%      pressure ------  跟结点号对应的压力值
%   返回值:
%      enf -----------  等效节点力向量
    global gNode
    
    enf = zeros( 9, 1 ) ;
    % 计算作用压力的三角形的面积
    x = gNode( node, 1 ) ;
    y = gNode( node, 2 ) ;
    z = gNode( node, 3 ) ;
    b = - det( [1  y(1) z(1)
                1  y(2) z(2)
                1  y(3) z(3)] ) ;
    c =   det( [1  x(1) z(1)
                1  x(2) z(2)
                1  x(3) z(3)] ) ;
    d = - det( [1  x(1) y(1)
                1  x(2) y(2)
                1  x(3) y(3)] ) ;
    A2 = sqrt( b^2 + c^2 + d^2 ) ;
    A = A2 / 2 ;

    % 计算三个结点上的等效节点力
    f1 = ( pressure(1)   + pressure(2)/2 + pressure(3)/2 ) / 6 * A ;
    f2 = ( pressure(1)/2 + pressure(2)   + pressure(3)/2 ) / 6 * A ;
    f3 = ( pressure(1)/2 + pressure(2)/2 + pressure(3)   ) / 6 * A ;
    
    % 计算三个方向上的分量
    nx = -b/A2 ;
    ny = -c/A2 ;
    nz = -d/A2 ;
    enf(1:3) = f1*[nx;ny;nz] ;
    enf(4:6) = f2*[nx;ny;nz] ;
    enf(7:9) = f3*[nx;ny;nz] ;
return

function es = ElementStress( ie )
%  计算单元的应力分量
%  输入参数
%      ie  ----- 单元号
%  返回值
%      es ----- 单元应力分量列阵(1×6): [sx, sy, sz, tyz, txz, txy]
    global gElement gDelta gMaterial
    
    de = zeros( 12, 1 ) ;   % 单元节点位移列阵
    E  = gMaterial( gElement(ie, 5), 1 ) ;
    mu = gMaterial( gElement(ie, 5), 2 ) ;
    A1 = mu/(1-mu) ;
    A2 = (1-2*mu)/2/(1-mu) ;
    A3 = E*(1-mu)/(1+mu)/(1-2*mu) ;
    D = [  1  A1  A1   0   0   0
          A1   1  A1   0   0   0
          A1  A1   1   0   0   0
           0   0   0  A2   0   0 
           0   0   0   0  A2   0
           0   0   0   0   0  A2] ;
    D = D * A3 ;
    B = MatrixB( ie ) ;
    for j=1:1:4
        de( 3*j-2 ) = gDelta( 3*gElement( ie, j )-2 ) ;
        de( 3*j-1 ) = gDelta( 3*gElement( ie, j )-1 ) ;
        de( 3*j   ) = gDelta( 3*gElement( ie, j )   ) ;
    end
    es = D * B * de ;
    es = transpose( es ) ;
return

function vol = ElementVolume( ie )
%  计算单元的体积
%  输入参数
%      ie  ----- 单元号
%  返回值
%      vol ----- 单元体积

    global gNode gElement
    
    % 读取结点坐标
    x = gNode( gElement( ie, : ), 1 ) ;
    y = gNode( gElement( ie, : ), 2 ) ;
    z = gNode( gElement( ie, : ), 3 ) ;
    
    % 计算 6V
    V6 = det( [1 x(1) y(1) z(1)
               1 x(2) y(2) z(2)
               1 x(3) y(3) z(3)
               1 x(4) y(4) z(4) ] ) ;
    
    vol = abs( V6/6 ) ;    
return

function B = MatrixB(ie)
%  计算单元的应变矩阵B
%  输入参数:
%     ie ----  单元号
%  返回值:
%     B  ----  单元应变矩阵

    global gNode gElement 
    
    % 读取结点坐标
    x = gNode( gElement( ie, : ), 1 ) ;
    y = gNode( gElement( ie, : ), 2 ) ;
    z = gNode( gElement( ie, : ), 3 ) ;
    
    % 计算 6V
    V6 = det( [1 x(1) y(1) z(1)
               1 x(2) y(2) z(2)
               1 x(3) y(3) z(3)
               1 x(4) y(4) z(4) ] ) ;
           
    % 计算应变矩阵
    B = zeros( 6, 12 ) ;
    for i=1:4
        j = mod(i,  4) + 1 ;
        m = mod(i+1,4) + 1 ;
        p = mod(i+2,4) + 1 ;
        bi = - det( [ 1 y(j) z(j)
                      1 y(m) z(m)
                      1 y(p) z(p) ] ) ;
        ci =   det( [ 1 x(j) z(j)
                      1 x(m) z(m)
                      1 x(p) z(p) ] ) ;
        di = - det( [ 1 x(j) y(j)
                      1 x(m) y(m)
                      1 x(p) y(p) ] ) ;
        B(:,(i-1)*3+1:(i-1)*3+3 ) = (-1)^(i+1)*[bi   0   0
                                                 0  ci   0
                                                 0   0  di
                                                 0  di  ci
                                                di   0  bi
                                                ci  bi   0] ;
    end
    B = B / V6 ;
return

function SaveResults( file_out ) 
%  保存计算结果
%  输入参数:
%     file_out ---- 存盘文件名
%  返回值:
%     无

    global gNode gElement gMaterial gBC1 gDF gNF gK gDelta gNodeStress gElementStress
    save( file_out, 'gNode', 'gElement', 'gMaterial', 'gBC1', ...
          'gDF', 'gNF', 'gDelta', 'gNodeStress', 'gElementStress' ) ;
return

function DisplayResults(file_out)
%  显示计算结果
%  输入参数:
%     无
%  返回值:
%     无
    y = [3,3.5,4,4.5] ;
    color = 'bgrc' ;
    [x,sy,syi] = exam5_1_post( file_out,y,0:0.25:4.5 ) ;
    figure ;
    hold ;
    for i=1:length(y)
        plot( x, sy(i,:),color(i) ) ;
    end
    legend( 'y=3.0','y=3.5','y=4.0','y=4.5' ) ;
    title( '离集中力不同距离处,正应力沿横截面的分布' ) ;
    xlabel( 'x' ) ;
    ylabel( '正应力' ) ;
    hold off ;
return

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -