Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Export of discontinuous fields to VTK #867

Draft
wants to merge 92 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
ed4972d
Rename vtk_point_data to vtk_node_data
KnutAM Apr 29, 2023
999571f
Merge master
KnutAM Apr 29, 2023
6c03c70
First attempts on VTKStream
KnutAM May 1, 2023
9a89a1a
Fix deprecations, stage 1
KnutAM May 1, 2023
53c9875
Make tests pass without updates
KnutAM May 1, 2023
f0d1537
Revert previous rename to vtk_node_data
KnutAM May 1, 2023
90e273b
Remove exports and revert example changes
KnutAM May 1, 2023
fbc75b6
Better deprecation warning
KnutAM May 1, 2023
65eace9
Minor docstring fix
KnutAM May 1, 2023
9dbb1de
Merge branch 'master' into kam/VTKStream
KnutAM May 10, 2023
cbaf610
Merge master
KnutAM Jul 5, 2023
77337ee
Fix test (wrong show overload)
KnutAM Jul 5, 2023
50c7c25
Create write_cell_colors and deprecate vtk_cell_data_colors
KnutAM Jul 5, 2023
9bd7131
Merge again
KnutAM Jul 5, 2023
ae917df
Fix show and remove filename from type
KnutAM Jul 7, 2023
58538a2
Merge branch 'master' into kam/VTKStream
KnutAM Jul 18, 2023
b64df44
Apply suggestions from code review
KnutAM Jul 18, 2023
077cf58
Export new functions and update docs
KnutAM Jul 18, 2023
cd6091b
Update tests with new functions
KnutAM Jul 18, 2023
a17e024
Remove (at)example from pseudo-code block in docs
KnutAM Jul 18, 2023
699aec2
Try to fix docs
KnutAM Jul 18, 2023
cf82d1c
Improve docs
KnutAM Jul 18, 2023
69a002c
pin documenter
KnutAM Jul 19, 2023
bff63b0
Renames and unexports
KnutAM Jul 19, 2023
ee61c6e
Fix tests
KnutAM Jul 19, 2023
22937f0
Use qualified name for write_cell_colors
KnutAM Jul 19, 2023
ccaeca2
Error instead of deprecation warning
KnutAM Jul 19, 2023
c5b21f7
Don't reexport WriteVTK
KnutAM Jul 19, 2023
2fdb656
Merge master
KnutAM Jul 19, 2023
6451632
More export fixes
KnutAM Jul 19, 2023
e49e8ac
Export VTKFile
KnutAM Jul 20, 2023
2398490
Tryout PVDFile
KnutAM Jul 23, 2023
91b5e20
Add close of pvd
KnutAM Jul 23, 2023
dda42e3
Remove qualified name
KnutAM Jul 23, 2023
8781ec4
Merge branch 'master' into kam/VTKStream
KnutAM Sep 15, 2023
f7c52ec
Merge branch 'master' into kam/PVDFile
KnutAM Sep 15, 2023
5dd7d65
Merge branch 'kam/PVDFile' into kam/VTKStream
KnutAM Sep 15, 2023
1cb8f99
Replace VTK.paraview_collection with ParaviewCollection
KnutAM Sep 15, 2023
51aeaf3
Merge master
KnutAM Sep 16, 2023
8a4c084
dev Ferrite from docs env
KnutAM Sep 16, 2023
5beaf6c
Doc improvements
KnutAM Sep 16, 2023
6487031
Document addstep
KnutAM Sep 16, 2023
dbc1ac3
Allow dofhandler input as alternative to grid
KnutAM Sep 16, 2023
cd1e303
Remove unused grid input in write_celldata and write_nodedata
KnutAM Sep 16, 2023
9226fed
Remove doc output and files
KnutAM Sep 16, 2023
db226ce
Merge manifest from master
KnutAM Sep 19, 2023
1770c08
Merge branch 'master' into kam/VTKStream
KnutAM Sep 19, 2023
57f0f33
ParaviewCollection -> VTKFileCollection
KnutAM Sep 19, 2023
ba5fbb1
Allow VTKFile keywords to be given to VTKFileCollection
KnutAM Sep 19, 2023
0a90f09
Factor out create_vtk_griddata
KnutAM Sep 25, 2023
6ad6b45
Merge branch 'master' into kam/VTKStream
KnutAM Sep 30, 2023
4cc50c6
Allow more vtk file types in VTKFile, e.g. pvtk
KnutAM Sep 30, 2023
193a375
Fix test failure due to merge
KnutAM Sep 30, 2023
112c4c2
Remove addstep and use VTKFile
KnutAM Sep 30, 2023
2047ab0
Revert "Remove addstep and use VTKFile"
KnutAM Sep 30, 2023
0cfbd24
Fix formatting in docstring
KnutAM Oct 1, 2023
12b8ed7
Support and test addstep[bang](pvd, vtk, t)
KnutAM Oct 14, 2023
e36b6cc
Merge branch 'master' into kam/VTKStream
KnutAM Oct 14, 2023
3e8d454
Allow input to VTKFileCollection ending with .pvd and update porous m…
KnutAM Oct 14, 2023
68b5d13
Export write_nodedata
KnutAM Oct 21, 2023
5aa6cb5
Remove kwargs forwarding
KnutAM Oct 21, 2023
419ce90
Merge master
KnutAM Dec 21, 2023
36322e2
Initial work on discontinuous vtk export
KnutAM Jan 7, 2024
eeb7b55
Initial POC
KnutAM Jan 8, 2024
431cf15
Merge branch 'master' into kam/VTKStream
KnutAM Jan 8, 2024
d1020fd
Update DG example to new syntax
KnutAM Jan 8, 2024
d8ad94f
Merge branch 'kam/VTKStream' into kam/VTK_discontinuous
KnutAM Jan 8, 2024
ea7f163
Merge branch 'master' into kam/VTKStream
KnutAM Feb 24, 2024
ffb9cd4
Merge branch 'kam/VTKStream' into kam/VTK_discontinuous
KnutAM Feb 24, 2024
6a17dac
Merge branch 'master' into kam/VTKStream
KnutAM Feb 28, 2024
5f828ff
Merge branch 'master' into kam/VTKStream
KnutAM Mar 1, 2024
5301307
Fix docs
KnutAM Mar 1, 2024
2f42748
Merge branch 'master' into kam/VTKStream
KnutAM Apr 25, 2024
d6f2ede
using VTKCellTypes explicitly
KnutAM Apr 26, 2024
f55c932
Change to using WriteVTK: vtk_grid
KnutAM Apr 26, 2024
b3fd680
Merge branch 'master' into kam/VTKStream
KnutAM May 16, 2024
fff96ad
Merge branch 'master' into kam/VTKStream
KnutAM May 16, 2024
62fa313
Merge master
KnutAM May 19, 2024
692cf78
Apply suggestions from code review
KnutAM May 19, 2024
4e84b76
write_cell_colors -> write_cellcolors
KnutAM May 19, 2024
acad0da
write_dirichlet -> write_constraints
KnutAM May 19, 2024
819bef6
Add missing tests for vtk export
KnutAM May 19, 2024
e405b38
Test deprecation error
KnutAM May 19, 2024
20668ef
Format test file
KnutAM May 19, 2024
5a0b4fb
Add changelog entry
KnutAM May 19, 2024
c69b9c6
Remove old mentions of "stream" in docstrings
KnutAM May 19, 2024
d6a199e
Add underscores to some names
KnutAM May 19, 2024
597fbf6
Merge kam/VTKStream
KnutAM May 19, 2024
eb960bc
Merge master
KnutAM May 24, 2024
e663cea
Fix merge errors
KnutAM May 24, 2024
726cbe4
Add test case
KnutAM May 24, 2024
e0cabaf
Make better test case showing node order is correct
KnutAM May 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/Export/VTK.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include("vtk_discontinuous.jl")

"""
VTKFile(filename::AbstractString, grid::AbstractGrid; kwargs...)
Expand Down Expand Up @@ -28,13 +29,21 @@ end
"""
struct VTKFile{VTK<:WriteVTK.VTKFile}
vtk::VTK
cellnodes::Vector{UnitRange{Int}}
end
function VTKFile(filename::String, dh::DofHandler; kwargs...)
for sdh in dh.subdofhandlers
for ip in sdh.field_interpolations
if is_discontinuous(ip)
return VTKFile(filename, get_grid(dh); write_discontinuous=true, kwargs...)
end
end
end
return VTKFile(filename, get_grid(dh); kwargs...)
end
function VTKFile(filename::String, grid::AbstractGrid; kwargs...)
vtk = create_vtk_grid(filename, grid; kwargs...)
return VTKFile(vtk)
function VTKFile(filename::String, grid::AbstractGrid; write_discontinuous=false, kwargs...)
vtk, cellnodes = create_vtk_grid(filename, grid, write_discontinuous; kwargs...)
return VTKFile(vtk, cellnodes)
end
# Makes it possible to use the `do`-block syntax
function VTKFile(f::Function, args...; kwargs...)
Expand All @@ -46,6 +55,8 @@ function VTKFile(f::Function, args...; kwargs...)
end
end

write_discontinuous(vtk::VTKFile) = length(vtk.cellnodes) > 0

Base.close(vtk::VTKFile) = WriteVTK.vtk_save(vtk.vtk)

function Base.show(io::IO, ::MIME"text/plain", vtk::VTKFile)
Expand Down Expand Up @@ -189,9 +200,14 @@ function create_vtk_griddata(grid::Grid{dim,C,T}) where {dim,C,T}
return coords, cls
end

function create_vtk_grid(filename::AbstractString, grid::Grid{dim,C,T}; kwargs...) where {dim,C,T}
coords, cls = create_vtk_griddata(grid)
return WriteVTK.vtk_grid(filename, coords, cls; kwargs...)
function create_vtk_grid(filename::AbstractString, grid::Grid{dim,C,T}, write_discontinuous; kwargs...) where {dim,C,T}
if write_discontinuous
coords, cls, cellnodes = create_discontinuous_vtk_griddata(grid)
else
coords, cls = create_vtk_griddata(grid)
cellnodes = Vector{UnitRange{Int}}(undef, 0)
end
return WriteVTK.vtk_grid(filename, coords, cls; kwargs...), cellnodes
end

function toparaview!(v, x::Vec{D}) where D
Expand Down Expand Up @@ -250,7 +266,11 @@ sorted by the nodes in the grid.
function write_solution(vtk::VTKFile, dh::AbstractDofHandler, u::Vector, suffix="")
fieldnames = Ferrite.getfieldnames(dh) # all primary fields
for name in fieldnames
data = _evaluate_at_grid_nodes(dh, u, name, #=vtk=# Val(true))
if write_discontinuous(vtk)
data = evaluate_at_discontinuous_vtkgrid_nodes(dh, u, name, vtk.cellnodes)
else
data = _evaluate_at_grid_nodes(dh, u, name, #=vtk=# Val(true))
end
_vtk_write_node_data(vtk.vtk, data, string(name, suffix))
end
return vtk
Expand Down
81 changes: 81 additions & 0 deletions src/Export/vtk_discontinuous.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
function create_discontinuous_vtk_griddata(grid::Grid{dim, C, T}) where {dim, C, T}
cls = Vector{WriteVTK.MeshCell}(undef, getncells(grid))
cellnodes = Vector{UnitRange{Int}}(undef, getncells(grid))
ncoords = sum(nnodes, getcells(grid))
coords = zeros(T, dim, ncoords)
icoord = 0
for cell in CellIterator(grid)
CT = getcelltype(grid, cellid(cell))
vtk_celltype = Ferrite.cell_to_vtkcell(CT)
cell_coords = getcoordinates(cell)
n = length(cell_coords)
cellnodes[cellid(cell)] = (1:n) .+ icoord
vtk_cellnodes = nodes_to_vtkorder(CT((ntuple(i->i+icoord, n))))
cls[cellid(cell)] = WriteVTK.MeshCell(vtk_celltype, vtk_cellnodes)
for x in cell_coords
icoord += 1
coords[:, icoord] = x
end
end
return coords, cls, cellnodes
end

function evaluate_at_discontinuous_vtkgrid_nodes(dh::DofHandler, u::Vector{T}, fieldname::Symbol, cellnodes) where T
# Make sure the field exists
fieldname ∈ getfieldnames(dh) || error("Field $fieldname not found.")
# Figure out the return type (scalar or vector)
field_idx = find_field(dh, fieldname)
ip = getfieldinterpolation(dh, field_idx)
RT = ip isa ScalarInterpolation ? T : Vec{n_components(ip),T}
n_c = n_components(ip)
vtk_dim = n_c == 2 ? 3 : n_c # VTK wants vectors padded to 3D
n_vtk_nodes = maximum(maximum, cellnodes)
data = fill(NaN * zero(T), vtk_dim, n_vtk_nodes)
# Loop over the subdofhandlers
for sdh in dh.subdofhandlers
# Check if this sdh contains this field, otherwise continue to the next
field_idx = _find_field(sdh, fieldname)
field_idx === nothing && continue

# Set up CellValues with the local node coords as quadrature points
CT = getcelltype(sdh)
ip = getfieldinterpolation(sdh, field_idx)
ip_geo = default_interpolation(CT)
local_node_coords = reference_coordinates(ip_geo)
qr = QuadratureRule{getrefshape(ip)}(zeros(length(local_node_coords)), local_node_coords)
if ip isa VectorizedInterpolation
# TODO: Remove this hack when embedding works...
cv = CellValues(qr, ip.ip, ip_geo)

Check warning on line 48 in src/Export/vtk_discontinuous.jl

View check run for this annotation

Codecov / codecov/patch

src/Export/vtk_discontinuous.jl#L48

Added line #L48 was not covered by tests
else
cv = CellValues(qr, ip, ip_geo)
end
drange = dof_range(sdh, field_idx)
# Function barrier
_evaluate_at_discontinuous_vtkgrid_nodes!(data, sdh, u, cv, drange, RT, cellnodes)
end
return data
end

function _evaluate_at_discontinuous_vtkgrid_nodes!(data::Matrix, sdh::SubDofHandler,
u::Vector{T}, cv::CellValues, drange::UnitRange, ::Type{RT}, cellnodes) where {T, RT}
ue = zeros(T, length(drange))
# TODO: Remove this hack when embedding works...
if RT <: Vec && function_interpolation(cv) isa ScalarInterpolation
uer = reinterpret(RT, ue)

Check warning on line 64 in src/Export/vtk_discontinuous.jl

View check run for this annotation

Codecov / codecov/patch

src/Export/vtk_discontinuous.jl#L64

Added line #L64 was not covered by tests
else
uer = ue
end
for cell in CellIterator(sdh)
# Note: We are only using the shape functions: no reinit!(cv, cell) necessary
@assert getnquadpoints(cv) == length(cell.nodes)
for (i, I) in pairs(drange)
ue[i] = u[cell.dofs[I]]
end
for (qp, nodeid) in pairs(cellnodes[cellid(cell)])
val = function_value(cv, qp, uer)
data[1:length(val), nodeid] .= val
data[(length(val)+1):end, nodeid] .= 0 # purge the NaN
end
end
return data
end
1 change: 0 additions & 1 deletion src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ export
write_node_data,
VTKFileCollection,
addstep!,

# L2 Projection
project,
L2Projector,
Expand Down
57 changes: 57 additions & 0 deletions test/test_vtk_export.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,61 @@
@test bytes2hex(open(SHA.sha1, fname*".vtu")) == "31b506bd9729b11992f8bcb79a2191eb65d223bf"
end
end

@testset "discontinuous" begin
# Produce a u such that the overall shape is f(x, xc) = 2 * (x[1]^2 - x[2]^2) - (xc[1]^2 - xc[2]^2)
# where xc is the center point of the cell. To avoid floating point issues for the hash,
# we test that all values are approximately an integer, and round to integers before storing.
function calculate_u(dh)
f(z) = z[1]^2 - z[2]^2
u = zeros(ndofs(dh))
ip = Ferrite.getfieldinterpolation(dh, (1, 1)) # Only one subdofhandler and one field.
cv = CellValues(QuadratureRule{RefQuadrilateral}(:lobatto, 2), ip)
for cell in CellIterator(dh)
reinit!(cv, cell)
# Cell center
xc = sum(getcoordinates(cell)) / getnquadpoints(cv)
for q_point in 1:getnquadpoints(cv)
x = spatial_coordinate(cv, q_point, getcoordinates(cell))
for i in 1:getnbasefunctions(cv)
δu = shape_value(cv, q_point, i)
val = δu * (f(x) * 2 - f(xc))
intval = round(Int, val)
# Ensure output unaffected by floating point errors,
# as we will compare vtk output with a hash
@assert abs(val - intval) < sqrt(eps())
u[celldofs(cell)[i]] += intval
end
end
end
return u
end

mktempdir() do tmp
nel = 20 # Dimensions assure integer coordinates at nodes and quad cell centers
xcorner = nel * ones(Vec{2})
grid = generate_grid(Quadrilateral, (nel, nel), -xcorner, xcorner)
# Good to keep for comparison:
# dh_cont = close!(add!(DofHandler(grid), :u, Lagrange{RefQuadrilateral,1}()))
# u_cont = calculate_u(dh_cont)
dh_dg = close!(add!(DofHandler(grid), :u, DiscontinuousLagrange{RefQuadrilateral,1}()))

u_dg = calculate_u(dh_dg)

testhash = "daf0cbe26ff709705f338526b19881ef5758f16b"

fname1 = joinpath(tmp, "discont_kwarg")
VTKFile(fname1, grid; write_discontinuous=true) do vtk
write_solution(vtk, dh_dg, u_dg)
end
@test bytes2hex(open(SHA.sha1, fname1*".vtu")) == testhash

fname2 = joinpath(tmp, "discont_auto")
VTKFile(fname2, dh_dg) do vtk
write_solution(vtk, dh_dg, u_dg)
end
@test bytes2hex(open(SHA.sha1, fname2*".vtu")) == testhash
end

end
end