code refactoring

This commit is contained in:
Jukka Aho
2016-06-27 16:11:33 +03:00
parent 90f7c581c5
commit 6993828927
20 changed files with 1627 additions and 362 deletions
+83 -19
View File
@@ -1,42 +1,77 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using JuliaFEM
"""
Calculate field values to nodal points from Gauss points using least-squares fitting.
"""
function calc_nodal_values!(elements, field_name, field_dim, time)
A = SparseMatrixCOO()
b = SparseMatrixCOO()
for element in elements
gdofs = get_connectivity(element)
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
f = ip(field_name, time)
N = element(ip, time)
add!(A, gdofs, gdofs, w*kron(N', N))
for dim=1:field_dim
add!(b, gdofs, w*f[dim]*N, dim)
function calc_nodal_values!(elements::Vector, field_name, field_dim, time;
F=nothing, nz=nothing, b=nothing, return_F_and_nz=false)
if F == nothing
A = SparseMatrixCOO()
for element in elements
gdofs = get_connectivity(element)
for ip in get_integration_points(element)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
add!(A, gdofs, gdofs, w*kron(N', N))
end
end
nz = get_nonzero_rows(A)
A = sparse(A)
A = 1/2*(A + A')
F = ldltfact(A[nz,nz])
end
A = sparse(A)
b = sparse(b)
nz = get_nonzero_rows(A)
if b == nothing
b = SparseMatrixCOO()
for element in elements
gdofs = get_connectivity(element)
for ip in get_integration_points(element)
if !haskey(ip, field_name)
info("warning: integration point does not have field $field_name")
continue
end
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
f = ip(field_name, time)
N = element(ip, time)
for dim=1:field_dim
add!(b, gdofs, w*f[dim]*N, dim)
end
end
end
b = sparse(b)
end
x = zeros(size(b)...)
x[nz, :] = A[nz,nz] \ b[nz, :]
x[nz, :] = F \ b[nz, :]
nodal_values = Dict()
for i=1:size(x,1)
nodal_values[i] = vec(x[i,:])
end
update!(elements, field_name, nodal_values)
update!(elements, field_name, time => nodal_values)
if return_F_and_nz
return F, nz
end
end
function calc_nodal_values!(problem::Problem, field_name, field_dim, time)
# after all, it's just a mass matrix ...
# isempty(problem.assembly.M) && assemble!(problem, time, Val{:mass_matrix}; density=1.0, dual_basis=false, dim=1)
# M = sparse(problem.assembly.M)
# TODO: make test before implementation
calc_nodal_values!(problem.elements, field_name, field_dim, time)
end
"""
Return node ids + vector of values
"""
function get_nodal_vector(elements, field_name, time)
f = Dict{Int64, Vector{Float64}}()
f = Dict()
for element in elements
for (c, v) in zip(get_connectivity(element), element[field_name](time))
if haskey(f, c)
@@ -50,3 +85,32 @@ function get_nodal_vector(elements, field_name, time)
return node_ids, field
end
""" Update nodal field values from set of elements to another. Can be used to
transform e.g. reaction force from boundary element set to surface of
volume elements for easier postprocess.
"""
function copy_field!(src_elements::Vector, dst_elements::Vector, field_name, time)
dst_nodes = Set{Int64}()
for element in dst_elements
push!(dst_nodes, get_connectivity(element)...)
end
node_ids, field = get_nodal_vector(src_elements, field_name, time)
z = 0.0*first(field)
d = Dict()
for j in dst_nodes
d[j] = z
end
for (j, f) in zip(node_ids, field)
d[j] = f
end
for element in dst_elements
c = get_connectivity(element)
f = [d[j] for j in c]
update!(element, field_name, time => f)
end
end
function copy_field!(src_problem::Problem, dst_problem::Problem, field_name, time)
copy_field!(src_problem.elements, dst_problem.elements, field_name, time)
end