Files
JuliaFEM.jl/src/problems_dirichlet.jl
T
Jukka Aho 1c67f1c1f8 Add postprocessing features (#100)
* refactored code for solvers.

* Added elementary tests for least-squares fitting of strain and stress fields

* A more realistic postprocess + Xdmf writing test

* removed debug keyword argument from test

* Rewrite update_xdmf!

New function to update Xdmf file no longer takes Solver object but
xdmf, problem, time and fields to write, for example

julia> update_xdmf!(xdmf, problem, 0.0, ["displacement", "temperature"])

All problems are written separately and put together into one
SpatialCollection, allowing to have more structured Xdmf and making
it easier to write complicated field configurations. Support for Xdmf
API 3.0 added.

* Support for Tensor6 field writing

* moved update_xdmf! to io.jl

* Removed some empty files

* Not use old Postprocessor, obsolete code.

* Not use old XDMF (obsolete code). Fixed test.

* removed some postprocessing to pass test, maybe we should drop abaqus.jl from code as obsolete

* add function get_temporal_collection back, it's used by update_xdmf of modal solver

* postprocess of boundary problems also

* added test for contact pressure. dl+quad test output was written in wrong file, fixed.

* postprocess for contact pressure

* contact pressure postprocess

* with boundary problems always store also the primary unknown field

* Change "reaction force" -> "lambda"

* testing postprocess of reaction force also

* sign convention
2017-03-21 08:36:18 +02:00

146 lines
4.8 KiB
Julia

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
"""
Problem u(X) = u₀ in Γ(d)
"""
type Dirichlet <: BoundaryProblem
formulation :: Symbol
variational :: Bool
dual_basis :: Bool
order :: Int
end
function Dirichlet()
Dirichlet(:incremental, false, false, 1)
end
function get_formulation_type(problem::Problem{Dirichlet})
return problem.properties.formulation
end
function assemble!(problem::Problem{Dirichlet}, time::Float64=0.0;
auto_initialize=true)
# FIXME: boilerplate
if !isempty(problem.assembly)
warn("Assemble problem $(problem.name): problem.assembly is not empty and assembling, are you sure you know what are you doing?")
end
if isempty(problem.elements)
warn("Assemble problem $(problem.name): problem.elements is empty, no elements in problem?")
else
first_element = first(problem.elements)
unknown_field_name = get_unknown_field_name(problem)
if !haskey(first_element, unknown_field_name)
warn("Assemble problem $(problem.name): seems that problem is uninitialized.")
if auto_initialize
info("Initializing problem $(problem.name) at time $time automatically.")
initialize!(problem, time)
end
end
end
if method_exists(assemble_prehook!, Tuple{typeof(problem), Float64})
assemble_prehook!(problem, time)
end
if problem.properties.variational
for element in get_elements(problem)
assemble!(problem.assembly, problem, element, time)
end
else # nodal collocation
field_vals = Dict{Int64, Float64}()
field_name = get_parent_field_name(problem)
field_dim = get_unknown_field_dimension(problem)
for element in get_elements(problem)
gdofs = get_gdofs(problem, element)
for i=1:field_dim
haskey(element, field_name*" $i") || continue
ldofs = gdofs[i:field_dim:end]
xis = get_reference_coordinates(typeof(element.properties))
vals = Float64[]
for xi in xis
g = element(field_name*" $i", xi, time)
# u = u_prev + Δu ⇒ Δu = u - u_prev
if haskey(element, field_name)
g_prev = element(field_name, xi, time)
g -= g_prev[i]
end
push!(vals, g)
end
for (dof, g) in zip(ldofs, vals)
field_vals[dof] = g
end
end
end
for (k, v) in field_vals
push!(problem.assembly.C1, k, k, 1.0)
push!(problem.assembly.C2, k, k, 1.0)
push!(problem.assembly.g, k, 1, v)
end
end
if method_exists(assemble_posthook!, Tuple{typeof(problem), Float64})
assemble_posthook!(problem, time)
end
end
function assemble!(assembly::Assembly, problem::Problem{Dirichlet},
element::Element, time::Float64)
# get dimension and name of PARENT field
nnodes = length(element)
field_dim = get_unknown_field_dimension(problem)
field_name = get_parent_field_name(problem)
gdofs = get_gdofs(element, field_dim)
props = problem.properties
if problem.properties.dual_basis
De, Me, Ae = get_dualbasis(element, time)
else
Ae = eye(nnodes)
De = zeros(nnodes, nnodes)
for ip in get_integration_points(element, props.order)
N = element(ip, time)
detJ = element(ip, time, Val{:detJ})
De += ip.weight*N'*N*detJ
end
end
# left hand side
for i=1:field_dim
ldofs = gdofs[i:field_dim:end]
if haskey(element, field_name*" $i")
add!(assembly.C1, ldofs, ldofs, De)
add!(assembly.C2, ldofs, ldofs, De)
end
end
# right hand side
for ip in get_integration_points(element, props.order)
detJ = element(ip, time, Val{:detJ})
w = ip.weight*detJ
N = element(ip, time)
for i=1:field_dim
ldofs = gdofs[i:field_dim:end]
if haskey(element, field_name*" $i")
g = element(field_name*" $i", ip, time)
# u = u_prev + Δu ⇒ Δu = u - u_prev
if haskey(element, field_name)
g_prev = element(field_name, ip, time)
g -= g_prev[i]
end
add!(assembly.g, ldofs, w*g*Ae*N')
end
end
end
end
function postprocess!(problem::Problem{Dirichlet}, time::Float64, ::Type{Val{Symbol("reaction force")}})
la = problem("lambda", time)
rf = Dict(nid => -lai for (nid, lai) in la)
update!(problem, "reaction force", time => rf)
end