有限元法的学习(一)

CST单元-有限元法理论与编程实现

有限元法的思想

有限元法作是一种数值计算的方法,是一种近似解的求解方式。首先,我们面对的问题通常是这样的一种问题,在对象的微元体中做分析,依据一些物理规律或者力学原理会得出相应的关系式,这种关系式一般会有两种情况,一是得出一个偏微分方程,即研究PDE在边界条件下的解答,也就是边值问题;二是得出一个泛函表达式,在边界条件下去研究问题的极值问题。因此,对于实际问题的研究就转化为数学上的研究,即偏微分方程的边值问题和泛函极值;对于PDE而言,在较复杂的情况下是难以获得解析解的,因此很有必要求解出一个可靠的近似解,数值计算就体现出了价值。对于PDE来说,可以利用有限差分法进行,或者其他方法(这点稍后再说),而泛函的求解除了经典的欧拉法外,应用最多的就是泛函的直接法,如rizi法,将所求的函数(称为场函数)用坐标系函数的线性组合来表示,然后带入到泛函中化简即可得到一个线性方程组,以此来完成求解。上述只是想说明,PDE和泛函各自都是有近似法可以去解答的,但是关键的一点是,泛函和PDE之间是可以相互转化的,从数学的角度而言,PDE所对应的泛函可以依据正定算子得到,泛函本身通过欧拉方程转化为PDE进行求解,结合物理意义而言这种数学上的转化就是我们说的一些泛函原理,如最小势能原理、虚功原理等。在明白了这个问题后,可以顺其自然地明白,如果对PDE进行求解是一件困难的事,那么要是将它转化为相应的泛函,然后求解泛函的极值,以此获得解答不就可以了吗?事实上,这种思路是很正确的、也是相当可行的一种思路。那么接下来一个很实际的问题就是如何转化?PDE方程依据最小余能原理可以表示为一个泛函为0的表达式,当然这种称为偏微分方程强的形式,利用分部积分法可以表述为弱的形式,这就将问题转化为了泛函极值的求解。那么接下来,为了得到近似解可以用rizi法,或者迦了金法(它本身就是用于求解PDE的,rizi法是直接对泛函进行操作的)。
有了上述的概念后,在看我们所面对的力学问题,在力的几大方程下,求出解是我们的目的,弹性力学中最后的方程本身就是一个椭圆偏微分方程,那么在比较困难的情况下(有时候写出方程本身就很困难),我们会想到将问题转化为泛函去完成求解,那么这之间必定要进行数学上的处理,作为一个力学问题,这种处理的物理意义是什么?这一点是很有理解的价值的,对于弹性体而言,最小势能原理就是这个转化的物理依据,这个原理是泛函原理中比较重要的一个,以此表示出泛函极值问题,然后求极值,会产生一个线性方程组,这个方程组的解答就是我们的最终解答,这一点上实际和rizi法一样,但是rizi法在选择场函数的近似表达时是从整个模型去考虑的,在边界条件复杂时,这种近似函数甚至无法找出,那么这个方法也就不具备可操作性了,而FEM的优点,在于单元化了研究对象,使得近似函数在一个小单元内部成立就行,不同单元具有位移连续性,那么组成到一起就可以表示整个研究对象,这也就是近似解和数值解的区别了,rizi法不是现代意义上的数值分析计算法,他只是泛函的直接法,但也是一种近似解的表达。
这就是对于有限元法的认识,如果仅从操作的角度讲,这些思考没啥价值,但是一旦我要去解决温度或者渗流、静电场的问题时,可能我就会束手无策了,因为对于其本质的理解不透彻,如果清楚明晰了它的思路和原理,那么实际上用有限元法求解问题就是用它去解一个PDE方程!!!它将PDE转化为泛函问题来进行求解,当然对一个仅有数学意义的PDE求解时,可能你找不到或者就不存在这种泛函原理,但是他背后的数学意义依然是成立,就是通过强的、弱的形式得到对应泛函!这就是我对于有限元法的一些认识。

CST单元

consist strain triangle简称为CST单元,即常应变单元。这是二维有限元法中最简单的一种单元。首先,需要明白的是我们面对的问题是什么,求解的量是谁?这个非常重要,一般来说我们都是按照位移进行求解,即场函数就是位移,得出来后依据几何方程、物理方程就可以确定出各点的应变、应力。当位移是一个一次式时,求导后自然是常数(求导后就得到应变),因此称为常应变三角形单元CST,这个单元模型所假设的位移模式是线性的,即单元内的位移变化是线性的,当然这和实际还是有出入的,但是这样的好处就是使得计算得到了很大程度地简化。

位移模式和形函数

实际上,对于一个力学分析问题而言,位移模式是进行有限元分析的第一步,位移模式主要意义就是将单元内的任一点的位移量(这个量其实就是我们的场函数)用该单元节点处的位移值来表示。场函数 ϕ=[u;v] ϕ = [ u ; v ] ,具体表达为

u(x,y)=a1+a2x+a3yv(x,y)=a4+a5x+a6y(3) (3) u ( x , y ) = a 1 + a 2 x + a 3 y v ( x , y ) = a 4 + a 5 x + a 6 y

即单元内一点处的位移是一个关于位置x,y的函数。CST单元我为三节点三角形单元,以逆时针命名编号,即i节点的坐标和位移值分别为 (xi,yi) ( x i , y i ) ui,vi u i , v i ;j节点、m节点的坐标和位移值分别为 (xj,yj) ( x j , y j ) (uj,vj) ( u j , v j ) (xm,ym) ( x m , y m ) (um,vm) ( u m , v m )
那么依据位移模式,节点的坐标和位移值本身就满足位移模式式(1),带入后会得到一个关于 ai a i 的方程组,求解出系数 ai a i

首先利用各点u的值来求解出 a1,a2,a3 a 1 , a 2 , a 3 ,方程组如下:

ui=a1+a2xi+a3yiuj=a1+a2xj+a3yjum=a1+a2xm+a3ym(4) (4) u i = a 1 + a 2 x i + a 3 y i u j = a 1 + a 2 x j + a 3 y j u m = a 1 + a 2 x m + a 3 y m

矩阵形式可以写为
a1a2a3=111xixjxmyiyjym1uiujum(3) (3) [ a 1 a 2 a 3 ] = [ 1 x i y i 1 x j y j 1 x m y m ] − 1 [ u i u j u m ]

由上述的方程组即可求解出系数a,为了方便后续的计算表达书写,可以另关于 xy x 、 y 的矩阵的逆矩阵为:

111xixjxmyiyjym1=12Aαiβiγiαjβjγjαmβmγm(4) (4) [ 1 x i y i 1 x j y j 1 x m y m ] − 1 = 1 2 A [ α i α j α m β i β j β m γ i γ j γ m ]

因此 ai,aj,am a i , a j , a m 为:
a1=12A(αiui+αjuj+αmum)a2=12A(βiui+βjuj+βmum)a3=12A(γiui+γjuj+γmum)(5) (5) a 1 = 1 2 A ( α i u i + α j u j + α m u m ) a 2 = 1 2 A ( β i u i + β j u j + β m u m ) a 3 = 1 2 A ( γ i u i + γ j u j + γ m u m )

实际上, α,β,γ α , β , γ 都是用节点坐标表示的。同理可以得出关于 a4,a5,a6 a 4 , a 5 , a 6 的解。因此将上述的公式表达带入到位移模式中去,并将式子按按照节点编号进行合并,可以得出
u(x,y)=12A[(αi+βix+γiy)ui+(αj+βjx+γjy)uj+(αm+βmx+γmy)um](6) (6) u ( x , y ) = 1 2 A [ ( α i + β i x + γ i y ) u i + ( α j + β j x + γ j y ) u j + ( α m + β m x + γ m y ) u m ]

因此,单元内的一点的横向位移u可以表示为这个单元各节点处的位移值和节点的坐标。同理,可以得出 v v 的表达,只需要将 u u 换为 v v 即可。
在上式中,可以引入一个函数 N N ,单元的形函数,他是关于x、y的一个函数:
Ni=12A(αi+βix+γiy)Nj=12A(αj+βjx+γjy)Nm=12A(αm+βmx+γmy)(7) (7) N i = 1 2 A ( α i + β i x + γ i y ) N j = 1 2 A ( α j + β j x + γ j y ) N m = 1 2 A ( α m + β m x + γ m y )

结合上述形函数的表达,单元内的位移可以表示为如下的矩阵形式:
[ψ]=[uv]=[Ni00NiNj00NjNm00Nm]uiviujvjumvm(8) (8) [ ψ ] = [ u v ] = [ N i 0 N j 0 N m 0 0 N i 0 N j 0 N m ] [ u i v i u j v j u m v m ]

即:
[ψ]=N×d(9) (9) [ ψ ] = N × d

单元的应变表达

实际上,在之前的位移模式分析中,主要的目的就是构建这样关系,用单元的节点坐标和节点处的场函数的值去表示出单元内一点处场函数(位移)。因此,在之前的分析基础上,我们实际上已经得到了单元内一点的位移表达,利用几何方程就可以确定出单元内一点处的应变。
几何方程矩阵表达形式为:

[ϵ]=ϵxϵyγxy=uxvyvx+uy=x0y0yx[uv](10) (10) [ ϵ ] = [ ϵ x ϵ y γ x y ] = [ ∂ u ∂ x ∂ v ∂ y ∂ v ∂ x + ∂ u ∂ y ] = [ ∂ ∂ x 0 0 ∂ ∂ y ∂ ∂ y ∂ ∂ x ] [ u v ]

将节点位移向量用之前所求出的表达式带入后得到
[ϵ]=x0y0yx[Ni00NiNj00NjNm00Nm][d](11) (11) [ ϵ ] = [ ∂ ∂ x 0 0 ∂ ∂ y ∂ ∂ y ∂ ∂ x ] [ N i 0 N j 0 N m 0 0 N i 0 N j 0 N m ] [ d ]

将算子矩阵和形状函数矩阵 N N 相乘,即可得到 3×6 3 × 6 的一个矩阵,令这个矩阵为 B B ,那么应变就可以表示:
ϵ=B×d(12) (12) ϵ = B × d

其中, B B 也称为几何矩阵,表达如下:
B=x0y0yx[Ni00NiNj00NjNm00Nm]=Nix0Niy0NiyNixNjx0Njy0NjyNjxNmx0Nmy0NmyNmx(13) (13) B = [ ∂ ∂ x 0 0 ∂ ∂ y ∂ ∂ y ∂ ∂ x ] [ N i 0 N j 0 N m 0 0 N i 0 N j 0 N m ] = [ ∂ N i ∂ x 0 ∂ N j ∂ x 0 ∂ N m ∂ x 0 0 ∂ N i ∂ y 0 ∂ N j ∂ y 0 ∂ N m ∂ y ∂ N i ∂ y ∂ N i ∂ x ∂ N j ∂ y ∂ N j ∂ x ∂ N m ∂ y ∂ N m ∂ x ]

在完成求导后,可以得到 B B 的具体表达。实际上, B B 中的元素是由 N N 求导后而得的,而 N N 由之前确定的表达来看是一个关于x,y的一次函数,因此 N N 的导数一定是一个常数,具体表达如下:
B=βi0γi0γiβiβj0γj0γjβjβm0γm0γmβm(14) (14) B = [ β i 0 β j 0 β m 0 0 γ i 0 γ j 0 γ m γ i β i γ j β j γ m β m ]

式中, βγ β 、 γ 的表达式如下:
βi=yjymβj=ymyiβm=yiyjγi=xmxjγj=xixmγm=xjxi(15) (15) β i = y j − y m β j = y m − y i β m = y i − y j γ i = x m − x j γ j = x i − x m γ m = x j − x i

单元应力

在得出单元内一点处的应变后,由物理方程可以求出应力表达,弹性力学中平面应力问题的物理方程如下:

σx=E1μ2(ϵx+μϵy)σy=E1μ2(μϵx+ϵy)τxy=E2(1+μ)γxy(16) (16) σ x = E 1 − μ 2 ( ϵ x + μ ϵ y ) σ y = E 1 − μ 2 ( μ ϵ x + ϵ y ) τ x y = E 2 ( 1 + μ ) γ x y

其矩阵表达形式如下:
σ=E1μ21μ0μ10001μ2ϵxϵyγxy(17) (17) σ = E 1 − μ 2 [ 1 μ 0 μ 1 0 0 0 1 − μ 2 ] [ ϵ x ϵ y γ x y ]

记为
σ=Dϵ(18) (18) σ = D ⋅ ϵ

单元刚度的表达

在进行完上述的计算后,对于一个单元来说,其内部的位移、应变、应力都得到了表达,这些都是连续介质力学中的量的表达,方程的获取需要进一步的分析,在传统的弹性力学中,解决问题实际上是需要几个基本方程联立的,但是在矩阵中这种操作十分的繁杂,因此不被利用。此外,再来看我们所面对的问题,如果是为了搞清楚连续介质在外力作用下的应力或者变形的话,依据位移求解时,在数学意义上其最终还是一个PDE方程的边值问题,因此会想到将其转化为泛函进行研究,进行这种变换的数学依据就是函数的内积,而在物理意义的层面就是依据各种变分原理,如最小势能原理、最小余能原理等。最小势能原理只能够应用于弹性体的推导,这是由于其表达式中引入了应力,必然会出现物理方程的相关描述。
* 最小势能原理
最小势能原理描述了物理处于平衡状态时它自身内部应力、应变的关系,这个原理认为一个处于平衡状态的物体,它内部的应力和应变之间的关系使得势能取得最小,即势能为极值时,这种状况下是平衡的。
令物体的势能为\pi_p,势能分为两部分一部分是物体自身变形所产生的应变能,实际上就是内部产生的形变所具有的弹性势能,另外一部分是外力势能,即外力在位移上做的功,外力做了多少功,外力势能就是多少,只不过符号是相反的。

πp=U+Ω(19) (19) π p = U + Ω

* 应变能U
U=12VϵTσdV(20) (20) U = 1 2 ∭ V ϵ T ⋅ σ d V

将之间所得到的应力、应变的表达带入后可以得到:
U=12VdTBTDBddV(21) (21) U = 1 2 ∭ V d T B T D B d d V

  • 外力势能 Ω Ω
    体力,即重力做的功 Ωb=VψTXdV=VdTNTXdV Ω b = − ∭ V ψ T X d V = − ∭ V d T N T X d V ,面力做的功产生的势能为 Ωs=SψTTsd=SdTNTTsdS Ω s = − ∬ S ψ T T s d = − ∬ S d T N T T s d S ,节点上的集中力做功产生的势能为 Ωp=dTP Ω p = − d T P
    由此可以得到物体的势能表达为
    πp=12dTVBTDBddVdTVNTXdVdTSNTTsdSdTP(22) (22) π p = 1 2 d T ∭ V B T D B d d V − d T ∭ V N T X d V − d T ∬ S N T T s d S − d T P

    如果对外力项进行合并引入一个f表示,即
    f=VNTXdV+SNTTsdV+P(23) (23) f = ∭ V N T X d V + ∬ S N T T s d V + P

    总势能表达为
    πp=12dTVBTDBddVdTf(24) (24) π p = 1 2 d T ∭ V B T D B d d V − d T f

    依据最小势能原理的表述,物体处于平衡状态,那么它的势能要取到极值。另外,上式实际上就是一个泛函,自变数就是d,节点的位移向量。即它的导数为0即为最小势能表达。
    πpd=VBTDBdVdf=0(25) (25) ∂ π p ∂ d = ∭ V B T D B d V d − f = 0

    因此,从上式可以看出单元的刚度矩阵k为
    k=VBTDBdV(26) (26) k = ∭ V B T D B d V

    在CST单元中,体积积分可以直接进行求解,因此可以得到刚度矩阵k的计算公式为
    k=BTDBtA(26) (26) k = B T D B t A

Matlab编程的实现

在Matlab中进行CST单元的有限元计算,为了清楚计算过程,该计算过程主要可以分解为5部分,每一部分完成个自己的任务,因此,各个部分使用的函数也具有不同的目的。将求解过程模块化,可以更方便地明晰计算思路,减小后期的debug工作量。

模型的网格化

主要目标
* 获得节点的坐标信息,存储于node矩阵中
* 获得各个单元的节点构成信息,存储于element矩阵中

使用到的函数

  • mesh2D函数
    不论有限元计算选取的单元是CST单元还是LST或者四边形单元,对于节点信息的要求是一致的,二维平面问题中,建立一个node矩阵,该大小矩阵为 n×2 n × 2 ,第一列存放节点的x坐标,第二列存放节点的y坐标,而该矩阵的行数的顺序就表示了节点编号。设节点总数为n,则node表示如下:
    [node]=x1x2..........xny1y2..........yn [ n o d e ] = [ x 1 y 1 x 2 y 2 . . . . . . . . . . . . . . . . . . . . x n y n ]

    在后续计算刚度矩阵时,需要对每个单元进行计算,而每个单元刚度矩阵的计算需要该单元的坐标信息,因此,仅仅知道node矩阵还无法完全的满足后续的要求,因此,需要一个element矩阵来记录各个单元的节点组成信息,这个矩阵要求节点的排序必须一致,对于不同的单元类型,这个矩阵的形状不同。对于CST单元来说,该单元是由三个节点构成,因此,element的行数自动认为是单元的编号,那么列元素则为组成这个单元的节点编号,通常节点按逆时针记录,对于CST单元来说,第一列表示单元的第一个节点,第二列、第三列,以此类推。需要注意的是,第一个节点的位置对于每个单元来说必须一致。
    [element]=num1num4......num2num5......num3num6...... [ e l e m e n t ] = [ n u m 1 n u m 2 n u m 3 n u m 4 n u m 5 n u m 6 . . . . . . . . . . . . . . . . . . ]

一些基本的模型几何信息。首先针对矩形模型,其底边边长 l l ,竖向边长 h h ,横向网格个数为m,竖向网格数为n,总节点数目为nnum,总单元数量为enum。mesh2D函数的目的就是通过已有的几何信息,以及对于网格密度的要求的输入,输出返回node、element矩阵。

% 模型几何以及网格基本信息
l =   ;
h =   ;
m =    ;
n =     ;
elenum = m*n*2;   %单元总数
nnum = (m+1)*(n+1);   %节点总数
deltl = l/m;
delth = h/n;

node function

function [node,element]=node(elenum,nnum,m,ndeltl,delth)
%获得node矩阵
node = zeros(elenum,2);   %初始化一个node矩阵,以提高循环效率
for i = 1:m+1  %以带宽最小为优先进行循环

    for j = 1:n+1

        nk = (i-1)*(n+1) + j;  %沿着短方向编号,
        node(nk,1) = (i-1)*deltl;   %确定x坐标
        node(nk,2) = (j-1)*delth;  %确定y坐标

    end

end

%获得element矩阵
element = zeros(elenum,3);   %初始化
for i = 1:m

    for j = 1:2*n

        ek = (i-1)*2*n+j;

        if mod(ek,2)==0 

                n1=(i-1)*(n+1)+j/2; 
                n2=i*(n+1)+j/2+1; 
                n3=(i-1)*(n+1)+j/2+1; 

        else

                n1=(i-1)*(n+1)+(j+1)/2; 
                n2=i*(n+1)+(j+1)/2; 
                n3=i*(n+1)+(j+1)/2+1; 

        end

                element(ek,:)=[n1,n2,n3]; 

    end

end    

end

mesh2D函数的一些解释
mesh2D函数的输入量有6个,顺序elenum,nnum,m,n,deltl,delth,即单元总数,节点总数,水平向间距数,竖向间距数,网格水平长度,网格竖向长度。首先进行的是node矩阵的计算,他的计算思路是,i和j分别控制矩阵索引的水平移动,和竖向移动。依据某个节点的i和j参数,确定出它的节点编号,沿着短方向进行编号,因此,模型上第一边上的点,序号就是1:n+1的循环,而第二边i=2时,只不过编号要在第一边的基础上进行叠加,因此用(i-1)*(n+1)+j来进行控制,由此确定出nk,当nk确定后,每计算一个nk,就对node(nk,:)进行坐标值的赋值。element矩阵的计算,相比于node要复杂,对于循环变量的确定不同于节点的,沿着水平方向看,i一定是从1取到m的,而竖向j是1到2*n的,思路和节点一致,先确定出一个ek,即单元的编号,然后立刻进行赋值。只不过这里通项公式会遇到奇偶问题,这个采取if-else语句来解决。

未完待续!!!

你可能感兴趣的:(Matlab数值计算,有限元法)