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

Make close actually save VTK files #149

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/grids/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ is equivalent to:
```julia
vtk = vtk_grid(filename, points..., [cells]; kws...)
# add datasets here...
saved_files = vtk_save(vtk)
saved_files = close(vtk)
```

## Data formatting options
Expand Down
2 changes: 1 addition & 1 deletion docs/src/metadata/multiblock.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ vtk = vtk_grid(yet_another_block, "my_deeply_nested_file", x4, y4, z4)
Finally, only the multiblock file needs to be saved explicitly:

``` julia
outfiles = vtk_save(vtm)
outfiles = close(vtm)
```

WriteVTK will write out a multiblock VTK file that looks like something like this (in addition to all the VTK files contained in the multiblock file):
Expand Down
4 changes: 2 additions & 2 deletions docs/src/metadata/parallel.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pvtk_grid(

which returns a handler representing a parallel VTK file that can be
appended with cell and point data and eventually written to disk with
[`vtk_save`](@ref) as usual.
In an MPI job, `vtk_save` will cause each rank to write a serial file and just
[`close`](@ref) as usual.
In an MPI job, `close` will cause each rank to write a serial file and just
a single rank (e.g., rank 0) will write the header file.

This signature is valid for **unstructured grids**.
Expand Down
4 changes: 2 additions & 2 deletions docs/src/metadata/paraview_collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ collection_add_timestep(pvd, vtk, time)
```

Here, `time` is a real number that represents the current time (or timestep) in
the simulation. Note that both options implicitly call `vtk_save(vtk)` so adding
the simulation. Note that both options implicitly call `close(vtk)` so adding
the VTK file to the collection must be done after adding data to the file.

When all the files are added to the `pvd` file, it can be saved using:

``` julia
vtk_save(pvd)
close(pvd)
```

## Working example
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tools/surface.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ julia> zs = @. cos(xs) + sin(ys');
julia> vtk = vtk_surface("surf", xs, ys, zs)
VTK file 'surf.vtu' (UnstructuredGrid file, open)

julia> vtk_save(vtk)
julia> close(vtk)
1-element Vector{String}:
"surf.vtu"
```
Expand Down
35 changes: 25 additions & 10 deletions src/WriteVTK.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@

using Base64: base64encode

import Base: close, isopen, show

using VTKBase:
VTKBase,
VTKCellTypes, # cell type definitions as in vtkCellType.h
Expand Down Expand Up @@ -50,7 +48,7 @@
"""
VTKFile

Abstract type describing a VTK file that may be written using [`vtk_save`](@ref).
Abstract type describing a VTK file that may be written using [`close`](@ref).
"""
abstract type VTKFile end

Expand Down Expand Up @@ -104,8 +102,10 @@
end
end

DatasetFile(dtype, xdoc::XMLDocument, fname::AbstractString, args...; kwargs...) =
function DatasetFile(dtype, xdoc::XMLDocument, fname::AbstractString, args...; kwargs...)
finalizer(LightXML.free, xdoc)
DatasetFile(xdoc, add_extension(fname, dtype), xml_name(dtype), args...; kwargs...)
end

function data_format(vtk::DatasetFile)
if vtk.appended
Expand All @@ -117,24 +117,39 @@
end
end

function show(io::IO, vtk::DatasetFile)
function Base.show(io::IO, vtk::DatasetFile)

Check warning on line 120 in src/WriteVTK.jl

View check run for this annotation

Codecov / codecov/patch

src/WriteVTK.jl#L120

Added line #L120 was not covered by tests
open_str = isopen(vtk) ? "open" : "closed"
print(io, "VTK file '$(vtk.path)' ($(vtk.grid_type) file, $open_str)")
end

"""
close(vtk::VTKFile)
Base.close(vtk::VTKFile) -> Vector{String}

Write and close VTK file.

Returns a list of paths pointing to the written VTK files (typically just one file, but can
be more for e.g. `MultiblockFile`).

---

Base.close(vtm::MultiblockFile) -> Vector{String}

Save and close multiblock file (`.vtm`).
The VTK files included in the multiblock file are also saved.
"""
close(vtk::VTKFile) = free(vtk.xdoc)
Base.close(vtk::VTKFile) = vtk_save(vtk) # for backwards compatibility, the actual implementation is in vtk_save (which still works)

# Free LightXML memory. Note that this is also called when an xdoc object is finalised, but
# it seems to be OK to call `free` multiple times.
# After calling this, the VTK file is considered as closed (see `isopen` below).
close_xml(vtk::VTKFile) = LightXML.free(vtk.xdoc)

"""
isopen(vtk::VTKFile)
Base.isopen(vtk::VTKFile)

Check if VTK file is still being written.
"""
isopen(vtk::VTKFile) = (vtk.xdoc.ptr != C_NULL)
Base.isopen(vtk::VTKFile) = (vtk.xdoc.ptr != C_NULL)

# Add a default extension to the filename, unless the user have already given
# the correct one.
Expand Down Expand Up @@ -201,7 +216,7 @@
try
f(vtk)
finally
outfiles = vtk_save(vtk)
outfiles = close(vtk)
end
outfiles :: Vector{String}
end
Expand Down
11 changes: 7 additions & 4 deletions src/gridtypes/ParaviewCollection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ struct CollectionFile <: VTKFile
xdoc::XMLDocument
path::String
timeSteps::Vector{String}
CollectionFile(xdoc, path) = new(xdoc, path, String[])
function CollectionFile(xdoc, path)
finalizer(LightXML.free, xdoc)
new(xdoc, path, String[])
end
end

function paraview_collection(filename::AbstractString;
Expand Down Expand Up @@ -65,7 +68,7 @@ function collection_add_timestep(pvd::CollectionFile, datfile::VTKFile,
set_attribute(xDataSet, "timestep", string(time))
set_attribute(xDataSet, "part", "0")
set_attribute(xDataSet, "file", fname)
append!(pvd.timeSteps, vtk_save(datfile))
append!(pvd.timeSteps, close(datfile))
return
end

Expand All @@ -75,8 +78,8 @@ Base.setindex!(pvd::CollectionFile, datfile::VTKFile, time::Real) =
function vtk_save(pvd::CollectionFile)
outfiles = [pvd.path; pvd.timeSteps]::Vector{String}
if isopen(pvd)
save_file(pvd.xdoc, pvd.path)
close(pvd)
LightXML.save_file(pvd.xdoc, pvd.path)
close_xml(pvd)
end
return outfiles
end
24 changes: 11 additions & 13 deletions src/gridtypes/multiblock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct VTKBlock
VTKBlock(xelm) = new(xelm, Union{VTKFile,VTKBlock}[])
end

Base.close(vtb::VTKBlock) = vtk_save(vtb)
xml_block_root(vtb::VTKBlock) = vtb.xelm

"""
Expand All @@ -21,7 +22,10 @@ struct MultiblockFile <: VTKFile
xdoc::XMLDocument
path::String
blocks::Vector{Union{VTKFile,VTKBlock}}
MultiblockFile(xdoc, path) = new(xdoc, path, Union{VTKFile,VTKBlock}[])
function MultiblockFile(xdoc, path)
finalizer(LightXML.free, xdoc)
new(xdoc, path, Union{VTKFile,VTKBlock}[])
end
end

function xml_block_root(vtm::MultiblockFile)
Expand All @@ -39,9 +43,9 @@ Initialise VTK multiblock file, linking multiple VTK dataset files.

Returns a handler for a multiblock file.
To recursively save the multiblock file and linked dataset files, call
[`vtk_save`](@ref) on the returned handler.
[`close`](@ref) on the returned handler.

Note that `vtk_save` is implicitly called if the optional `f` argument is passed.
Note that `close` is implicitly called if the optional `f` argument is passed.
This is in particular what happens when using the do-block syntax.
"""
function vtk_multiblock(filename::AbstractString)
Expand Down Expand Up @@ -103,20 +107,14 @@ function _generate_gridfile_basename(vtm::VTKBlock)
end
end

"""
vtk_save(vtm::MultiblockFile)

Save and close multiblock file (`.vtm`).
The VTK files included in the multiblock file are also saved.
"""
function vtk_save(vtm::MultiblockFile)
outfiles = [vtm.path]::Vector{String}
for vtk in vtm.blocks
append!(outfiles, vtk_save(vtk))
append!(outfiles, close(vtk))
end
if isopen(vtm)
save_file(vtm.xdoc, vtm.path)
close(vtm)
LightXML.save_file(vtm.xdoc, vtm.path)
close_xml(vtm)
end
outfiles
end
Expand All @@ -125,7 +123,7 @@ function vtk_save(vtm::VTKBlock)
# Saves VTKBlocks.
outfiles = String[]
for vtk in vtm.blocks
append!(outfiles, vtk_save(vtk))
append!(outfiles, close(vtk))
end
return outfiles
end
Expand Down
12 changes: 8 additions & 4 deletions src/gridtypes/pvtk_grid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ struct PVTKFile <: VTKFile
xdoc::XMLDocument
vtk::DatasetFile
path::String
function PVTKFile(args, xdoc, vtk, path)
finalizer(LightXML.free, xdoc)
new(args, xdoc, vtk, path)
end
end

# This is just to make a PVTKFile work like a DatasetFile.
Expand Down Expand Up @@ -52,9 +56,9 @@ compute_whole_extent(::Nothing) = nothing
)

Returns a handler representing a parallel VTK file, which can be
eventually written to file with `vtk_save`.
eventually written to file with [`close`](@ref).

Positional and keyword arguments in `args` and `kwargs` are passed to `vtk_grid`
Positional and keyword arguments in `args` and `kwargs` are passed to [`vtk_grid`](@ref)
verbatim.
Note that serial filenames are automatically generated from `filename` and from
the process id `part`.
Expand Down Expand Up @@ -186,8 +190,8 @@ function vtk_save(pvtk::PVTKFile)
save_file(pvtk.xdoc, pvtk.path)
push!(outfiles, pvtk.path)
end
append!(outfiles, vtk_save(pvtk.vtk))
close(pvtk)
append!(outfiles, close(pvtk.vtk))
close_xml(pvtk)
end
outfiles
end
Expand Down
4 changes: 2 additions & 2 deletions src/save_files.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ function vtk_save(vtk::DatasetFile)
save_file(vtk.xdoc, vtk.path)
end
end
if isopen(vtk) # just in case the file was closed by calls to save_* above
close(vtk)
if isopen(vtk) # just in case the XML handler was freed by calls to save_* above
close_xml(vtk)
end
return [vtk.path] :: Vector{String}
end
Expand Down
6 changes: 4 additions & 2 deletions test/pvdCollection.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env julia

using WriteVTK
using Test

using Printf: @sprintf

Expand Down Expand Up @@ -69,7 +70,8 @@ function main()
vtk["q_values"] = q
vtk["myVector"] = vec
vtk["myCellData"] = cdata
vtk_save(vtk)
close(vtk)
@test isopen(vtk) == false
pvd[float(it + 1)] = vtk
end
end
Expand All @@ -83,7 +85,7 @@ function main()
# add a vtk file
vtk_reload = vtk_grid("collection_reload", [1, 2, 3], [1, 2, 3])
pvd_reload[5.0] = vtk_reload
pvd_reload_files = vtk_save(pvd_reload)
pvd_reload_files = close(pvd_reload)
append!(outfiles, pvd_reload_files)

println("Saved: ", join(outfiles, " "))
Expand Down
3 changes: 2 additions & 1 deletion test/rectilinear.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ function main()
vtk["myCellData"] = cdata

# Save and close vtk file.
append!(outfiles, vtk_save(vtk))
append!(outfiles, close(vtk))
@test isopen(vtk) == false
end

end # dim loop
Expand Down
6 changes: 5 additions & 1 deletion test/structured.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using WriteVTK
using StaticArrays: SVector
using Test

const FloatType = Float32
const vtk_filename_noext = "structured"
Expand Down Expand Up @@ -111,8 +112,11 @@ function generate_structured(grid_format, ::Val{dim}) where {dim}
vtk["myVector.SVector"] = vs

# Save and close vtk file.
vtk_save(vtk)
files = close(vtk)
@test isopen(vtk) == false
end

files
end

function main()
Expand Down
4 changes: 3 additions & 1 deletion test/surface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ files = String[]
let
@time output = let
vtk = vtk_surface("surface_basic", xs, ys, zs)
vtk_save(vtk)
output = close(vtk)
@test isopen(vtk) == false
output
end
append!(files, output)
end
Expand Down
Loading