mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-10-03 22:57:57 +00:00
fixes
This commit is contained in:
+89
-58
@@ -22,9 +22,14 @@ type Assembly
|
||||
D :: SparseMatrixCOO
|
||||
g :: SparseMatrixCOO
|
||||
|
||||
solution :: Vector{Float64} # full solution vector when solving problem Ax = b
|
||||
previous_solution :: Vector{Float64} # previous solution vector
|
||||
solution_norm_change :: Real # for convergence studies
|
||||
u :: Vector{Float64} # solution vector u
|
||||
u_prev :: Vector{Float64} # previous solution vector u
|
||||
u_norm_change :: Real # change of norm in u
|
||||
|
||||
la :: Vector{Float64} # solution vector la
|
||||
la_prev :: Vector{Float64} # previous solution vector u
|
||||
la_norm_change :: Real # change of norm in la
|
||||
|
||||
prehooks :: Vector{Tuple{Symbol,Any,Any}} # assign possible prehooks before assembly
|
||||
posthooks :: Vector{Tuple{Symbol,Any,Any}} # assign possible posthooks after assembly
|
||||
changed :: Bool # flag to control is reassembly needed
|
||||
@@ -40,6 +45,7 @@ function Assembly()
|
||||
SparseMatrixCOO(),
|
||||
SparseMatrixCOO(),
|
||||
[], [], Inf,
|
||||
[], [], Inf,
|
||||
[], [], true)
|
||||
end
|
||||
|
||||
@@ -101,22 +107,87 @@ function get_assembly(problem)
|
||||
return problem.assembly
|
||||
end
|
||||
|
||||
""" Update problem solution vector.
|
||||
""" Initialize unknown field ready for nonlinear iterations, i.e.,
|
||||
take last known value and set it as a initial quess for next
|
||||
time increment.
|
||||
"""
|
||||
function update!(problem::Problem, solution::Vector{Float64})
|
||||
function initialize!(problem::Problem, time::Real)
|
||||
field_name = get_unknown_field_name(problem)
|
||||
field_dim = get_unknown_field_dimension(problem)
|
||||
for element in get_elements(problem)
|
||||
gdofs = get_gdofs(element, problem)
|
||||
if haskey(element, field_name)
|
||||
# if field is found, copy last known solution to new time as initial guess
|
||||
if !isapprox(last(element[field_name]).time, time)
|
||||
last_data = copy(last(element[field_name]).data)
|
||||
push!(element[field_name], time => last_data)
|
||||
end
|
||||
else # if field not found at all, initialize new zero field.
|
||||
data = Vector{Float64}[zeros(field_dim) for i in 1:length(element)]
|
||||
element[field_name] = (time => data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
""" Update problem solution vector for assembly. """
|
||||
function update_assembly!(problem, u, la)
|
||||
|
||||
assembly = get_assembly(problem)
|
||||
# resize & fill with zeros solution vector if length mismatch with current solution
|
||||
if length(solution) != length(assembly.solution)
|
||||
resize!(assembly.solution, length(solution))
|
||||
fill!(assembly.solution, 0.0)
|
||||
|
||||
# resize & fill with zeros vectors if length mismatch with current solution
|
||||
if length(u) != length(assembly.u)
|
||||
resize!(assembly.u, length(u))
|
||||
fill!(assembly.u, 0.0)
|
||||
end
|
||||
assembly.previous_solution = copy(assembly.solution)
|
||||
if length(la) != length(assembly.la)
|
||||
resize!(assembly.la, length(la))
|
||||
fill!(assembly.la, 0.0)
|
||||
end
|
||||
|
||||
# copy current solutions to previous ones and add/replace new solution
|
||||
assembly.u_prev = copy(assembly.u)
|
||||
assembly.la_prev = copy(assembly.la)
|
||||
if get_formulation_type(problem) == :incremental
|
||||
assembly.solution += solution
|
||||
assembly.u += u
|
||||
assembly.la += la
|
||||
else
|
||||
assembly.solution = solution
|
||||
assembly.u = u
|
||||
assembly.la = la
|
||||
end
|
||||
|
||||
# calculate change of norm
|
||||
assembly.u_norm_change = norm(assembly.u - assembly.u_prev)
|
||||
assembly.la_norm_change = norm(assembly.la - assembly.la_prev)
|
||||
return assembly.u_norm_change, assembly.la_norm_change
|
||||
end
|
||||
|
||||
""" Update solutions to elements.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This assumes that element is properly initialized so that last known field data
|
||||
is from current time. For boundary problems solution is updated from lambda vector
|
||||
and for field problems from actual solution vector.
|
||||
"""
|
||||
function update_elements!(problem, u, la)
|
||||
field_name = get_unknown_field_name(problem)
|
||||
field_dim = get_unknown_field_dimension(problem)
|
||||
nnodes = round(Int, length(u)/field_dim)
|
||||
|
||||
solution = nothing
|
||||
if is_field_problem(problem)
|
||||
solution = reshape(u, field_dim, nnodes)
|
||||
elseif is_boundary_problem(problem)
|
||||
solution = reshape(la, field_dim, nnodes)
|
||||
else
|
||||
error("update_elements!(): unknown problem type $(typeof(problem))")
|
||||
end
|
||||
|
||||
for element in get_elements(problem)
|
||||
connectivity = get_connectivity(element) # node ids
|
||||
local_sol = Vector{Float64}[solution[:, node_id] for node_id in connectivity]
|
||||
last(element[field_name]).data = local_sol
|
||||
end
|
||||
assembly.solution_norm_change = norm(assembly.solution - assembly.previous_solution)
|
||||
end
|
||||
|
||||
#=
|
||||
@@ -144,52 +215,12 @@ function get_unknown_field_name{P}(problem::Problem{P})
|
||||
return get_unknown_field_name(P)
|
||||
end
|
||||
|
||||
""" Return the name of the parent field of this (boundary) problem. """
|
||||
function get_parent_field_name{P<:BoundaryProblem}(problem::Problem{P})
|
||||
return problem.parent_field_name
|
||||
end
|
||||
|
||||
function push!(problem::Problem, element)
|
||||
push!(problem.elements, element)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# TODO: better place for utility functions?
|
||||
|
||||
""" Calculate "nodal" vector from set of elements.
|
||||
|
||||
For example element 1 with dofs [1, 2, 3, 4] has [1, 1, 1, 1] and
|
||||
element 2 with dofs [3, 4, 5, 6] has [2, 2, 2, 2] the result will
|
||||
be sparse matrix with values [1, 1, 3, 3, 2, 2].
|
||||
|
||||
Parameters
|
||||
----------
|
||||
field_name
|
||||
name of field, e.g. "geometry"
|
||||
field_dim
|
||||
degrees of freedom / node
|
||||
elements
|
||||
elements used to calculate vector
|
||||
time
|
||||
"""
|
||||
function calculate_nodal_vector(field_name::ASCIIString, field_dim::Int, elements::Vector{Element}, time::Real)
|
||||
A = SparseMatrixCOO()
|
||||
b = SparseMatrixCOO()
|
||||
for element in elements
|
||||
haskey(element, field_name) || continue
|
||||
gdofs = get_gdofs(element, 1)
|
||||
for ip in get_integration_points(element, Val{2})
|
||||
J = get_jacobian(element, ip, time)
|
||||
w = ip.weight*norm(J)
|
||||
f = element(field_name, ip, 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)
|
||||
end
|
||||
end
|
||||
end
|
||||
A = sparse(A)
|
||||
b = sparse(b)
|
||||
nz = sort(unique(rowvals(A)))
|
||||
x = zeros(size(b)...)
|
||||
x[nz, :] = A[nz,nz] \ b[nz, :]
|
||||
return vec(transpose(x))
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user