matrices for dual formulation for elements

This commit is contained in:
Jukka Aho
2016-02-05 11:32:09 +02:00
parent d8047c6af0
commit e1540b609b
2 changed files with 40 additions and 35 deletions
+13 -26
View File
@@ -23,27 +23,19 @@ function assemble!(assembly::Assembly, problem::Problem{Dirichlet}, element::Ele
field_name = get_parent_field_name(problem)
gdofs = get_gdofs(element, field_dim)
# calculate bi-orthogonal basis transformation matrix Ae
nnodes = size(element, 2)
De = zeros(nnodes, nnodes)
Me = zeros(nnodes, nnodes)
for ip in get_integration_points(element, Val{2})
w = ip.weight
J = get_jacobian(element, ip, time)
JT = transpose(J)
if size(JT, 2) == 1 # plane problem
w *= norm(JT)
else
w *= norm(cross(JT[:,1], JT[:,2]))
end
N = element(ip, time)
De += w*diagm(vec(N))
Me += w*N'*N
end
Ae = De*inv(Me)
De, Me, Ae = get_dualbasis(element, time)
# do the actual integration
for ip in get_integration_points(element, Val{2})
# left hand side
for i=1:field_dim
ldofs = gdofs[i:field_dim:end]
if haskey(element, field_name*" $i") || haskey(element, field_name)
add!(assembly.C1, ldofs, ldofs, De)
add!(assembly.C2, ldofs, ldofs, De)
end
end
# right hand side
for ip in get_integration_points(element, Val{3})
w = ip.weight
J = get_jacobian(element, ip, time)
JT = transpose(J)
@@ -54,15 +46,11 @@ function assemble!(assembly::Assembly, problem::Problem{Dirichlet}, element::Ele
end
N = element(ip, time)
Phi = (Ae*N')'
A = w*Phi'*N
A[abs(A) .< 1.0e-12] = 0
if haskey(element, field_name)
for i=1:field_dim
g = element(field_name, ip, time)
ldofs = gdofs[i:field_dim:end]
add!(assembly.C1, ldofs, ldofs, A)
add!(assembly.C2, ldofs, ldofs, A)
add!(assembly.g, ldofs, w*g*Phi')
end
else
@@ -70,13 +58,12 @@ function assemble!(assembly::Assembly, problem::Problem{Dirichlet}, element::Ele
ldofs = gdofs[i:field_dim:end]
if haskey(element, field_name*" $i")
g = element(field_name*" $i", ip, time)
add!(assembly.C1, ldofs, ldofs, A)
add!(assembly.C2, ldofs, ldofs, A)
add!(assembly.g, ldofs, w*g*Phi')
end
end
end
end
end
#=
+27 -9
View File
@@ -6,7 +6,10 @@ abstract AbstractElement
type Element{E}
connectivity :: Vector{Int}
fields :: Dict{ASCIIString, Field}
dualbasis :: Matrix{Float64} # coefficients to construct dual basis
# matrices to construct dual basis
D :: Matrix{Float64}
M :: Matrix{Float64}
A :: Matrix{Float64}
end
function Base.size{E}(::Element{E})
@@ -18,8 +21,7 @@ function Base.size{E}(::Element{E}, i::Int64)
end
function convert{E}(::Type{Element{E}}, connectivity::Vector{Int})
# return Element{E}(connectivity, get_integration_points(E), Dict())
return Element{E}(connectivity, Dict(), Matrix())
return Element{E}(connectivity, Dict(), Matrix(), Matrix(), Matrix())
end
function get_integration_points{E}(element::Element{E}, args...)
@@ -184,22 +186,38 @@ function call{E}(element::Element{E}, xi::VecOrIP, time::Float64=0.0)
return get_basis(element, xi)
end
function call(element::Element, xi::VecOrIP, time::Real, ::Type{Val{:dualbasis}})
""" Return dual basis transformation matrix Ae. """
function get_dualbasis(element::Element, time::Real)
if length(element.dualbasis) == 0
nnodes = size(element, 2)
De = zeros(nnodes, nnodes)
Me = zeros(nnodes, nnodes)
D = zeros(nnodes, nnodes)
M = zeros(nnodes, nnodes)
for ip in get_integration_points(element, Val{3})
w = ip.weight
J = get_jacobian(element, ip, time)
w = ip.weight*norm(J)
JT = transpose(J)
if size(JT, 2) == 1 # plane problem
# || ∂X/∂ξ ||
w *= norm(JT)
else
# || ∂X/∂ξ₁ × ∂X/∂ξ₂ ||
w *= norm(cross(JT[:,1], JT[:,2]))
end
N = element(ip, time)
De += w*diagm(vec(N))
Me += w*N'*N
end
element.dualbasis = De*inv(Me)
element.D = D
element.M = M
element.A = De*inv(Me)
end
return element.D, element.M, element.A
end
function call(element::Element, xi::VecOrIP, time::Real, ::Type{Val{:dualbasis}})
De, Me, Ae = get_dualbasis(element, time)
N = get_basis(element, xi)
Phi = element.dualbasis*N'
Phi = Ae*N'
return Phi'
end