Files
JuliaFEM.jl/src/postprocess_xdmf.jl
T
2016-06-27 16:11:33 +03:00

196 lines
6.6 KiB
Julia

# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
using LightXML
using JuliaFEM
# element codes: http://www.paraview.org/pipermail/paraview/2013-July/028859.html
# > from ./VTK/ThirdParty/xdmf2/vtkxdmf2/libsrc/XdmfTopology.h
# >
# > // Topologies
# > #define XDMF_NOTOPOLOGY 0x0
# > #define XDMF_POLYVERTEX 0x1
# > #define XDMF_POLYLINE 0x2
# > #define XDMF_POLYGON 0x3
# > #define XDMF_TRI 0x4
# > #define XDMF_QUAD 0x5
# > #define XDMF_TET 0x6
# > #define XDMF_PYRAMID 0x7
# > #define XDMF_WEDGE 0x8
# > #define XDMF_HEX 0x9
# > #define XDMF_EDGE_3 0x0022
# > #define XDMF_TRI_6 0x0024
# > #define XDMF_QUAD_8 0x0025
# > #define XDMF_QUAD_9 0x0023
# > #define XDMF_TET_10 0x0026
# > #define XDMF_PYRAMID_13 0x0027
# > #define XDMF_WEDGE_15 0x0028
# > #define XDMF_WEDGE_18 0x0029
# > #define XDMF_HEX_20 0x0030
# > #define XDMF_HEX_24 0x0031
# > #define XDMF_HEX_27 0x0032
# > #define XDMF_MIXED 0x0070
# > #define XDMF_2DSMESH 0x0100
# > #define XDMF_2DRECTMESH 0x0101
# > #define XDMF_2DCORECTMESH 0x0102
# > #define XDMF_3DSMESH 0x1100
# > #define XDMF_3DRECTMESH 0x1101
# > #define XDMF_3DCORECTMESH 0x1102
get_xdmf_element_code(element::Element{Poi1}) = 0x0001
get_xdmf_element_code(element::Element{Seg2}) = 0x0002
get_xdmf_element_code(element::Element{Seg3}) = 0x0003
get_xdmf_element_code(element::Element{Tri3}) = 0x0004
get_xdmf_element_code(element::Element{Quad4}) = 0x0005
get_xdmf_element_code(element::Element{Tet4}) = 0x0006
get_xdmf_element_code(element::Element{Hex8}) = 0x0009
get_xdmf_element_code(element::Element{Tet10}) = 0x0026
type XDMF
dimension :: Int
use_hdf :: Bool
xdoc :: XMLDocument
domain :: XMLElement
temporal_collection :: XMLElement
current_grid
permutation :: Vector{Int}
end
function XDMF()
xdoc = XMLDocument()
xroot = create_root(xdoc, "Xdmf")
set_attribute(xroot, "xmlns:xi", "http://www.w3.org/2001/XInclude")
set_attribute(xroot, "Version", "2.1")
domain = new_child(xroot, "Domain")
temporal_collection = new_child(domain, "Grid")
set_attribute(temporal_collection, "CollectionType", "Temporal")
set_attribute(temporal_collection, "GridType", "Collection")
set_attribute(temporal_collection, "Name", "Collection")
return XDMF(3, false, xdoc, domain, temporal_collection, Union{}, [])
end
function xdmf_new_result!(xdmf::XDMF, elements::Vector, time)
grid = new_child(xdmf.temporal_collection, "Grid")
set_attribute(grid, "Name", "Grid")
time_ = new_child(grid, "Time")
set_attribute(time_, "Value", time)
xdmf.current_grid = grid
# 1. calculate permutation
nids = Set()
X = Dict{Int64, Vector{Float64}}()
for element in elements
conn = get_connectivity(element)
push!(nids, conn...)
X_el = element["geometry"](time)
for (i, c) in enumerate(conn)
X[c] = X_el[i]
end
end
xdmf.permutation = sort(collect(nids))
iperm = Dict{Int64, Int64}()
for (i, j) in enumerate(xdmf.permutation)
iperm[j] = i
end
# 2. write nodes
geometry = new_child(grid, "Geometry")
set_attribute(geometry, "Type", xdmf.dimension == 3 ? "XYZ" : "XY")
dataitem = new_child(geometry, "DataItem")
set_attribute(dataitem, "DataType", "Float")
set_attribute(dataitem, "Format", "XML")
#set_attribute(dataitem, "Precision", 8)
s = ASCIIString[]
ndim = 0
for i in xdmf.permutation
ndim += length(X[i])
push!(s, join(round(X[i], 5), " "))
end
set_attribute(dataitem, "Dimensions", ndim)
add_text(dataitem, "\n"*join(s, "\n")*"\n")
# 3. write elements
topology = new_child(grid, "Topology")
set_attribute(topology, "TopologyType", "Mixed")
set_attribute(topology, "NumberOfElements", length(elements))
dataitem = new_child(topology, "DataItem")
set_attribute(dataitem, "Format", "XML")
set_attribute(dataitem, "DataType", "Int")
# set_attribute(dataitem, "Precision", 8)
s = ASCIIString[]
eldim = 0
for element in elements
eltype = get_xdmf_element_code(element)
# note: id numbers start from 0 in Xdmf
conn = [iperm[j] for j in get_connectivity(element)] - 1
data = [eltype; conn]
eldim += length(data)
push!(s, join(data, " "))
end
set_attribute(dataitem, "Dimensions", eldim)
add_text(dataitem, "\n"*join(s, "\n")*"\n")
end
function xdmf_save_field!(xdmf, elements::Vector, time, field_name; field_type="Scalar", debug=false)
f = Dict()
field_dim = 0
for element in elements
haskey(element, field_name) || continue
g = element[field_name](time)
conn = get_connectivity(element)
for (i, c) in enumerate(conn)
gi = g[i]
if (field_type == "Vector") && (length(gi) < 3)
# paraview goes crazy if 2d model with 2d displacement vector
gi = [gi; 0.0]
end
if field_dim == 0
field_dim = length(gi)
end
field_dim == length(gi) || error("several dimensions in field, dim = $field_dim.")
f[c] = gi
end
end
if length(f) == 0
warn("xdmf_save_field!(): field $field_name was not found from set of elements")
return
end
attribute = new_child(xdmf.current_grid, "Attribute")
set_attribute(attribute, "Center", "Node")
set_attribute(attribute, "Name", ucfirst(field_name))
set_attribute(attribute, "Type", field_type)
dataitem = new_child(attribute, "DataItem")
set_attribute(dataitem, "DataType", "Float")
set_attribute(dataitem, "Format", "XML")
#set_attribute(dataitem, "Precision", 8)
debug && info("field dim = $field_dim")
debug && info(f)
s = ASCIIString[]
dim = 0
for i in xdmf.permutation
gi = zeros(field_dim)
if haskey(f, i)
gi = f[i]
end
push!(s, join(round(gi, 5), " "))
dim += length(gi)
end
set_attribute(dataitem, "Dimensions", dim)
add_text(dataitem, "\n"*join(s, "\n")*"\n")
end
function xdmf_save_field!(xdmf, problem::Problem, time, field_name; field_type="Scalar")
xdmf_save_field!(xdmf, problem.elements, time, field_name; field_type=field_type)
end
function xdmf_new_result!(xdmf, problem::Problem, time)
xdmf_new_result!(xdmf, problem.elements, time)
end
function xdmf_save!(xdmf, filename)
save_file(xdmf.xdoc, filename)
end