Exporters#
Write a mesh and its grid functions to a file a viewer can open: VTK for ParaView, or pgfplots data for LaTeX.
Bramble.export_vtk
source
export_vtk(filename::AbstractString, Ωₕ::AbstractMeshType, fields::Pair...) -> Vector{String}
export_vtk(filename::AbstractString, uₕ::VectorElement, name::AbstractString = "u") -> Vector{String}
Write Ωₕ, and any number of named fields over it, to a VTK rectilinear grid file (.vtr).
Each entry in fields is name => data, where data is a VectorElement over a grid space on Ωₕ (scalar or composite) or a plain array already shaped like the grid. A composite whose components live on different meshes throws an ArgumentError: export each component against its own mesh. The second method is a shorthand for a single field, named "u" unless told otherwise.
A 1D mesh gets a degenerate second axis rather than being refused: VTK has no dedicated 1D grid type, but a rectilinear grid one point deep in y opens and renders correctly.
Requires WriteVTK.jl; call using WriteVTK before calling this.
Examples
using Bramble, WriteVTK
Ωₕ = mesh(domain(interval(0.0, 1.0) × interval(0.0, 1.0)), (20, 20), (true, true))
Wₕ = gridspace(Ωₕ)
uₕ = Rₕ(Wₕ, x -> sin(x[1]) * x[2])
export_vtk("solution", Ωₕ, "u" => uₕ) # writes solution.vtr
export_vtk("solution", uₕ) # the same field, named "u"
See also export_vtk(f::Function, filename) below, for a time series of these.
export_vtk(f::Function, filename::AbstractString; append::Bool = false) -> Vector{String}
Write a ParaView time-series collection (.pvd) alongside the .vtr file each step of f writes, closing the collection when f returns and when it throws – an interrupted run leaves a valid, readable partial animation rather than truncated XML.
f is called with a collection handle pvd; assign into it with pvd[t] = (step_filename, Ωₕ, fields...), the same (filename, Ωₕ, name => data, ...) shape export_vtk itself takes, once per time value t. Steps do not need a uniform spacing: t is recorded exactly as given, which is what an adaptive OrdinaryDiffEq integrator's own saved times already are.
Keywords
append:trueto append new steps to an existing.pvdatfilenamerather than overwrite it (defaultfalse).
Requires WriteVTK.jl; call using WriteVTK before calling this.
Examples
using Bramble, WriteVTK
Ωₕ = mesh(domain(interval(0.0, 1.0)), 41, true)
Wₕ = gridspace(Ωₕ)
export_vtk(joinpath(mktempdir(), "wave")) do pvd
for (i, t) in enumerate((0.0, 0.3, 1.0))
uₕ = Rₕ(Wₕ, x -> sin(x[1] - t))
pvd[t] = ("step_$(lpad(i, 3, '0'))", Ωₕ, "u" => uₕ)
end
end
See also export_vtk(filename, Ωₕ, fields...) above, for a single snapshot, and export_vtk(filename, Wₕ, sol) below, for a one-call SciMLBase solution export.
export_vtk(filename::AbstractString, Wₕ::AbstractSpaceType, sol;
name::AbstractString = "u", times = nothing) -> Vector{String}
Write a SciMLBase ODE solution sol – the result of solving an ode_problem – as a ParaView time-series collection (.pvd), one .vtr step per saved (or interpolated) time.
sol.u[i] is a plain coefficient vector with no shape of its own; Wₕ, the space the problem was built over, is what turns it back into a properly reshaped field, the same way element(Wₕ, ::AbstractVector) does anywhere else.
Keywords
name: the field name written at every step (default"u"). One call writes one field. For several named fields per step (solution, coefficient, error, ...), useexport_vtk(f::Function, filename)directly.times:nothing(default) writes exactlysol's own saved steps, at their true, possibly non-uniform values – the common case for an adaptive integrator. With an iterable of times, each is sampled fromsol's continuous interpolation (sol(t)).
Requires WriteVTK.jl and SciMLBase.jl (pulled in by any solver package, e.g. OrdinaryDiffEq); call using WriteVTK before calling this.
Examples
using Bramble, WriteVTK, OrdinaryDiffEqBDF
prob = ode_problem(sd, u₀, I)
sol = solve(prob, FBDF())
export_vtk(joinpath(mktempdir(), "solution"), Wₕ, sol) # every saved step
export_vtk(joinpath(mktempdir(), "solution"), Wₕ, sol; times = 0:0.1:1.0) # interpolated
See also ode_problem, element.
Bramble.export_pgfplots
source
export_pgfplots(filename::AbstractString, Ωₕ::AbstractMeshType{1}, fields::Pair...) -> String
export_pgfplots(filename::AbstractString, Ωₕ::AbstractMeshType{2}, field::Pair) -> String
export_pgfplots(filename::AbstractString, uₕ::VectorElement, name::AbstractString = "u") -> String
Write grid data to a plain-text table, laid out the way pgfplots reads it directly: no external package needed, since the format is just whitespace-separated numbers.
On a 1D mesh, any number of named fields become columns: x name₁ name₂ ..., one row per grid point, readable with \addplot table {file.dat} or \addplot table[y=name] {file.dat} to pick one column by name. A composite VectorElement expands into one column per component, named name_1, name_2, and so on. A composite whose components live on different meshes throws an ArgumentError: export each component against its own mesh.
On a 2D mesh, exactly one field is written as x y z triples (pgfplots' surf/mesh format has no way to encode more than one value per point) with a blank line after each run of constant x. That blank line is what tells \addplot3[surf] table {file.dat} where one row of the grid ends and the next begins; without it the same numbers plot as a shredded zigzag instead of a surface. A composite element is refused with a message saying so, rather than silently writing one of its components.
data in a field pair can be a VectorElement, or a plain array already shaped like the grid (a vector in 1D, a vector or a (nx, ny) matrix in 2D).
A 3D mesh is refused: \addplot3[surf] plots a height field over a 2D domain, not a true 3D volume, so a 3D mesh has no faithful representation in this format. See export_vtk.
Examples
using Bramble
Ωₕ = mesh(domain(interval(0.0, 1.0)), 33, true)
Wₕ = gridspace(Ωₕ)
uₕ = Rₕ(Wₕ, sin)
export_pgfplots("curve", Ωₕ, "u" => uₕ) # writes curve.dat
Ω2 = mesh(domain(interval(0.0, 1.0) × interval(0.0, 1.0)), (20, 20), (true, true))
W2 = gridspace(Ω2)
v2 = Rₕ(W2, x -> sin(x[1]) * x[2])
export_pgfplots("surface", Ω2, "u" => v2) # writes surface.dat, for \addplot3[surf]