有限元形函数及JuliaFEM中的实现方式
形函数
形函数也称插值函数,是构造单元内某点坐标、位移与单元顶点坐标或位移关系的函数。构造时需先假定单元的位移模式,一般用多项式表达,如三节点三角形单元采用 1+u+v,四节点四边形单元用1+u+v+u*v。插值函数是节点坐标与位移模式多项式的函数。
位移模式
我们以三角形单元为例说明形函数的构造方法:
1.三角形单元的位移模式为1+u+v;
2. 三个顶点的坐标分别为
(
x
i
,
y
i
)
,
(
x
j
,
y
j
)
,
(
x
m
,
y
m
)
(x_{i},y_{i}),(x_{j},y_{j}),(x_{m},y_{m})
(xi,yi),(xj,yj),(xm,ym),对应局部坐标系下的坐标为(0,0),(1,0),(0,1);
3. 单元内任意点的位移可通过下式表达:
(1)
u
=
α
1
+
α
2
x
+
α
3
y
v
=
α
4
+
α
5
x
+
α
6
y
u=\alpha_{1}+ \alpha_{2} x+\alpha_{3}y\newline v=\alpha_{4}+ \alpha_{5} x+\alpha_{6}y \tag{1}
u=α1+α2x+α3yv=α4+α5x+α6y(1)
4.将节点坐标带入(1)式,可得顶点处的位移为:
u
i
=
α
1
+
α
2
x
i
+
α
3
y
i
u
j
=
α
1
+
α
2
x
j
+
α
3
y
j
u
m
=
α
1
+
α
2
x
m
+
α
3
y
m
v
i
=
α
4
+
α
5
x
i
+
α
6
y
i
v
j
=
α
4
+
α
5
x
j
+
α
6
y
j
v
m
=
α
4
+
α
5
x
m
+
α
6
y
m
u_{i}=\alpha_{1}+ \alpha_{2} x_{i}+\alpha_{3}y_{i}\newline u_{j}=\alpha_{1}+ \alpha_{2} x_{j}+\alpha_{3}y_{j}\newline u_{m}=\alpha_{1}+ \alpha_{2} x_{m}+\alpha_{3}y_{m}\newline v_{i}=\alpha_{4}+ \alpha_{5} x_{i}+\alpha_{6}y_{i}\newline v_{j}=\alpha_{4}+ \alpha_{5} x_{j}+\alpha_{6}y_{j}\newline v_{m}=\alpha_{4}+ \alpha_{5} x_{m}+\alpha_{6}y_{m}\newline
ui=α1+α2xi+α3yiuj=α1+α2xj+α3yjum=α1+α2xm+α3ymvi=α4+α5xi+α6yivj=α4+α5xj+α6yjvm=α4+α5xm+α6ym
即:
(2)
{
u
i
u
j
u
m
}
=
[
1
x
i
y
i
1
x
j
y
j
1
x
m
y
m
]
∗
{
α
1
α
2
α
3
}
\left\{\begin{matrix} u_{i}\\ u_{j} \\ u_{m} \\ \end{matrix}\right\} = \left[ \begin{matrix} 1&x_{i}&y_{i}\\ 1&x_{j}&y_{j}\\ 1&x_{m}&y_{m} \\ \end{matrix} \right] * \left\{\begin{matrix} \alpha_{1}\\ \alpha_{2} \\ \alpha_{3} \\ \end{matrix}\right\}\tag{2}
⎩⎨⎧uiujum⎭⎬⎫=⎣⎡111xixjxmyiyjym⎦⎤∗⎩⎨⎧α1α2α3⎭⎬⎫(2)
令:
[
T
]
=
[
1
x
i
y
i
1
x
j
y
j
1
x
m
y
m
]
\left[ \begin{matrix} T \end{matrix} \right] = \left[ \begin{matrix} 1&x_{i}&y_{i}\\ 1&x_{j}&y_{j}\\ 1&x_{m}&y_{m} \\ \end{matrix} \right]
[T]=⎣⎡111xixjxmyiyjym⎦⎤
JuliaFEM中[T]矩阵的实现
[T]中“列”为位移模式中多项式在i,j,m处的数值。JuliaFEM中包FEMBasis中的vandermonde.jl主要用于实现[T]矩阵。
'''
vandermonde_matrix(polynomial, coordinates)
Given some polynomial and coordinates points (1-3 dimensions), create a Vandermonde
matrix.
# Example
To genererate a Vandermonde matrix for a reference quadrangle `[-1.0, 1.0]^2` for
polynomial `p(u,v) = 1 + u + v + u*v`, one writes:
polynomial = :(1 + u + v + u*v)
coordinates = ((-1.0,-1.0), (1.0,-1.0), (1.0,1.0), (-1.0,1.0))
V = vandermonde_matrix(polynomial, coordinates)
# output
[
1.0 -1.0 -1.0 1.0
1.0 1.0 -1.0 -1.0
1.0 1.0 1.0 1.0
1.0 -1.0 1.0 -1.0
]
'''
function vandermonde_matrix(polynomial::Expr, coordinates::NTuple{N, NTuple{D, T}}) where {N, D, T<:Number}
A = zeros(N, N)
first(polynomial.args) == :+ || error("Use only summation between terms of polynomial")
args = polynomial.args[2:end]
for i in 1:N
X = coordinates[i]
if D == 1
data = (:u => X[1],)
elseif D == 2
data = (:u => X[1], :v => X[2])
elseif D == 3
data = (:u => X[1], :v => X[2], :w => X[3])
end
for (j, term) in enumerate(args)
A[i,j] = subs(term, data)
end
end
return A
end
代码中subs()主要实现用数值代替表达式中的变量进行计算;
'''
subs(expression, data)
Given expression and pair(s) of `symbol => value` data, substitute to expression.
# Examples
Let us have polynomial `1 + u + v + u*v^2`, and substitute u=1 and v=2:
expression = :(1 + u + v + u*v^2)
data = (:u => 1.0, :v => 2.0)
subs(expression, data)
8.0
'''
function subs(p::Expr, data::NTuple{N,Pair{Symbol, T}}) where {N, T}
for di in data
p = subs(p, di)
end
return simplify(p)
end
上述三角形单元生产的[T]矩阵为:
julia> p= :(1+u+v)
:(1 + u + v)
julia> X=(
(0.0, 0.0), # i
(1.0, 0.0), # j
(0.0, 1.0), # m
)
((0.0, 0.0), (1.0, 0.0), (0.0, 1.0))
julia> V=vandermonde_matrix(p,X)
3×3 Array{Float64,2}:
1.0 0.0 0.0
1.0 1.0 0.0
1.0 0.0 1.0
形函数定义
将(2)进行推导可得:
(3)
{
α
1
α
2
α
3
}
=
[
T
]
−
1
∗
{
u
i
u
j
u
m
}
\left\{ \begin{matrix} \alpha_{1}\\ \alpha_{2} \\ \alpha_{3} \\ \end{matrix} \right\}= \left[ \begin{matrix} T \end{matrix} \right] ^{-1} * \left\{\begin{matrix} u_{i}\\ u_{j} \\ u_{m} \\ \end{matrix}\right\} \tag{3}
⎩⎨⎧α1α2α3⎭⎬⎫=[T]−1∗⎩⎨⎧uiujum⎭⎬⎫(3)
将(3)式带入(1)式可得:
(4)
u
=
[
1
u
v
]
∗
[
T
]
−
1
∗
{
u
i
u
j
u
m
}
u= \left[ \begin{matrix} 1&u&v \end{matrix} \right] * \left[ \begin{matrix} T \end{matrix} \right] ^{-1} * \left\{\begin{matrix} u_{i}\\ u_{j} \\ u_{m} \\ \end{matrix}\right\} \tag{4}
u=[1uv]∗[T]−1∗⎩⎨⎧uiujum⎭⎬⎫(4)
定义形函数:
[
N
]
=
[
1
u
v
]
∗
[
T
]
−
1
\left[ \begin{matrix} N \end{matrix} \right]=\left[ \begin{matrix} 1&u&v \end{matrix} \right] * \left[ \begin{matrix} T \end{matrix} \right] ^{-1}
[N]=[1uv]∗[T]−1
这里的坐标为局部坐标,由
[
T
]
∗
[
T
]
−
1
=
[
E
]
\left[ \begin{matrix} T \end{matrix} \right]* \left[ \begin{matrix} T \end{matrix} \right] ^{-1} = \left[ \begin{matrix} E \end{matrix} \right]
[T]∗[T]−1=[E]
那么
[
T
]
∗
[
X
1
]
=
[
1
0
0
]
\left[ \begin{matrix} T \end{matrix} \right]*[X1]= \left[ \begin{matrix} 1\\ 0\\ 0 \end{matrix} \right]
[T]∗[X1]=⎣⎡100⎦⎤这里的X1为[T]^{-1}的第一列,同理
[
T
]
∗
[
X
2
]
=
[
0
1
0
]
这
里
的
X
2
为
[
T
]
−
1
的
第
二
列
。
\left[ \begin{matrix} T \end{matrix} \right]*[X2]= \left[ \begin{matrix} 0\\ 1\\ 0 \end{matrix} \right]这里的X2为[T]^{-1}的第二列。
[T]∗[X2]=⎣⎡010⎦⎤这里的X2为[T]−1的第二列。
Julia中形函数的实现
create_basis.jl中的calculate_interpolation_polynomials(p,v)函数用于计算形函数,参数p为位移模式多项式(p::Expr)如:(1+u+v),参数v即为上述的[T]矩阵。
function calculate_interpolation_polynomials(p, V)
basis = []
first(p.args) == :+ || error("Use only summation between terms of polynomial")
args = p.args[2:end]
N = size(V, 1)
b = zeros(N)
for i in 1:N
fill!(b, 0.0)
b[i] = 1.0
#计算逆矩阵的单列
solution = V \ b
N = Expr(:call, :+)
for (ai, bi) in zip(solution, args)
isapprox(ai, 0.0) && continue
#位移模式多项式如[1 u v]与逆矩阵的单列相乘并放入数组中
push!(N.args, simplify( :( $ai * $bi ) ))
end
push!(basis, N)
end
return basis
end
Julia中形函数导数的实现
主要通过Calculus模块中differentiate(N,var)函数,N为形函数,var为[:u, :v, :w]
function calculate_interpolation_polynomial_derivatives(basis, D)
vars = [:u, :v, :w]
dbasis = []
for N in basis
partial_derivatives = []
for j in 1:D
#分别对u v w进行求导
push!(partial_derivatives, simplify(differentiate(N, vars[j])))
end
push!(dbasis, partial_derivatives)
end
return dbasis
end