API Reference
Data source
FerriteViz.FEData — Type
FEData(dh::Ferrite.AbstractDofHandler, u::Vector; topology, adaptive=true)Source node of the visualization pipeline: builds the static "L2" triangulation of Ferrite.get_grid(dh) (nodes shared between cells are duplicated per cell so discontinuous fields render with their jumps) and holds u as an Observable for live updating via FerriteViz.update!.
Named data arrays are resolved with point_data/cell_data and registered with set_point_data!/set_cell_data!. Transformations are applied by piping into filters: ds |> WarpByVector(:u, 2.0) |> Gradient(:u) |> VonMises().
For large 3D grids, pass a precomputed topology::Ferrite.ExclusiveTopology to avoid rebuilding it.
adaptive=true (the default) tessellates with the Refine filter's automatic choice: cell types whose geometry and fields are all (multi-)linear keep the flat base tessellation, everything else is subdivided so curved and high-order-deformed cells render curved — at the price of more triangles (see Refine for the numbers). Opt out with adaptive=false (flat base tessellation for every cell); custom levels are a filter application: FEData(dh, u; adaptive=false) |> Refine(2).
FerriteViz.update! — Function
FerriteViz.update!(ds::FEData, u::Vector)Update the source solution observable, propagating through all filters and open plots down to the GPU buffers. Can be called on any dataset of a pipeline; it always updates the root solution (u must match its length).
Not exported: both Makie and Ferrite export distinct functions named update!, so call this one qualified.
FerriteViz.point_data — Function
point_data(ds::FEData, name::Symbol) -> Observable{Matrix{Float64}}The named data array on the tessellation vertices (nvertices × ncomponents; tensor components in Tensors.jl linear order). These are the vertices of the triangulation the dataset renders, not the vertices of the finite element cells — see the architecture overview. Fields of the dof handler are transferred to the tessellation lazily and cached; :default resolves to the first field.
:default is reserved for this purpose wherever a name is expected, so a dof handler carrying a field named :default is rejected by FEData.
FerriteViz.cell_data — Function
cell_data(ds::FEData, name::Symbol) -> ObservableThe named per-cell data array (length ncells), registered via set_cell_data!.
FerriteViz.set_point_data! — Function
set_point_data!(ds::FEData, name::Symbol, data)Register a named data array on the tessellation vertices (see num_vertices — one row per vertex of the rendered triangulation, not per grid node). data may be a Vector/Matrix or an Observable of one — updates to a registered Observable propagate into plots. Existing names are overwritten; dof field names cannot be shadowed.
FerriteViz.set_cell_data! — Function
set_cell_data!(ds::FEData, name::Symbol, data)Register a named per-cell data array (length ncells, any element type — e.g. stress tensors, to be reduced by filters like VonMises). data may be a Vector or an Observable of one. Existing names are overwritten; dof field names cannot be shadowed.
Filters
Filters transform an FEData into a new one and compose with |>:
ds = FEData(dh, u)
solutionplot(ds |> WarpByVector(:u, 2.0) |> Gradient(:u) |> VonMises(); color=:vonMises)FerriteViz.apply — Function
apply(f::AbstractFilter, ds::FEData) -> FEDataApply a filter to a dataset. Filters are callable, so ds |> f is equivalent.
FerriteViz.WarpByVector — Type
WarpByVector(field=:default, scale=1.0)Filter displacing the geometry (tessellation vertices and grid nodes) by scale times the vector-valued field. scale may be a number or an Observable (e.g. driven by a slider). Warps compose: the displacement is added to the input dataset's current coordinates.
field may name any vector-valued point-data array; the tessellation vertices (surfaces and the meshplot wireframe) always follow. The original grid nodes (meshplot's node markers and labels) can only be displaced when the field is a dof-backed field of the dof handler and stay put otherwise.
FerriteViz.Gradient — Type
Gradient(field=:default; copy_fields=Symbol[])Filter computing the piecewise discontinuous gradient of field (via interpolate_gradient_field). The output dataset's field is named :gradient; fields listed in copy_fields are carried along. Geometry (including an upstream warp) is shared with the input.
FerriteViz.CrinkleClip — Type
CrinkleClip(decision)Filter hiding the cells for which decision(grid, cellid) is false, revealing the (crinkled) interior along the clip surface. decision is typically a ClipPlane.
FerriteViz.ClipPlane — Type
ClipPlane{T}(normal, distance_to_origin)Clip plane described by its normal and distance to the coordinate origin, for use as the decision function of CrinkleClip: callable as plane(grid, cellid), returning whether the cell lies on the non-clipped side.
FerriteViz.Refine — Type
Refine() # automatic, what FEData applies by default
Refine(n::Int; edges=n)
Refine(; surface=nothing, edges=nothing)Filter re-tessellating every cell from its reference shape with a subdivided reference tessellation (see FerriteViz.subdivide): surface rounds for the rendered triangles (each round quadruples them, refining the rendered solution), edges rounds for the wireframe segments drawn by meshplot (each round doubles them, refining the rendered geometry edges). The subdivided reference vertices are mapped through the cell's geometric interpolation, so curved (high-order) geometry and high-order deformation render curved instead of as flat facets and straight chords.
The counts are absolute, not relative to the input's tessellation: Refine(2) yields 2 subdivision rounds regardless of how the dataset was tessellated before.
A count given as nothing is chosen per cell type: no subdivision when the geometry and every dof field are (multi-)linear, otherwise 1 surface and 3 edge rounds. FEData applies this automatic mode by default — construct with adaptive=false to opt out, e.g. to subdivide only one branch of a pipeline:
ds = FEData(dh, u; adaptive=false)
meshplot(ds) # flat, cheap
solutionplot(ds |> Refine(2)) # this plot resolved finerEvery surface round quadruples the rendered triangles and roughly triples the tessellation vertices (each of which carries solution values per field). The automatic mode therefore costs high-order cell types about 4× the memory of the flat tessellation; edge rounds are comparatively cheap (segments only double). On large high-order grids opt out with FEData(dh, u; adaptive=false).
The choice made for a nothing count may change in a future release; such a change is breaking. Explicit counts are stable.
Rebuilds the geometry from the grid (a quadrature-point partition of AddQuadraturePointData does not survive — nor would it gain anything from refinement, its data being piecewise constant), so apply WarpByVector after it; registered point data is dropped, cell data survives.
FerriteViz.AddQuadraturePointData — Type
AddQuadraturePointData(qr, values; output=:qpdata, extract=identity)Filter for internal variables, i.e. quantities that carry a value only at the quadrature points and have no interpolation defining them anywhere else (in FEM terms: L2 data). Every cell is partitioned into the Voronoi regions of its quadrature points (see FerriteViz.qp_voronoi_tessellation) and each region is filled with its quadrature point's value, giving a piecewise constant ("flat") rendering that neither averages over the cell nor smooths the data onto a nodal field.
qr is a Ferrite.QuadratureRule, or a Dict mapping reference shapes to rules for grids with mixed cell types.
values may be
- a
Vectorof per-cell vectors (values[cell][qp];nqpmay differ per cell), - a
Matrix(values[cell, qp], requiring a uniformnqp), or - an
Observableof either — updating it refreshes all open plots.
extract maps a stored entry to the plotted value, so Ferrite material states can be handed over directly (extract = s -> s.εₚ). Scalars, Vecs and (symmetric) second order tensors are supported. The result is registered as point data named output and can be reduced further with VonMises, Derive, ...
Rebuilds the geometry, so apply WarpByVector after this filter.
Example
FEData(dh, u) |> AddQuadraturePointData(qr, states; extract = s -> s.σ) |> VonMises(input = :qpdata)FerriteViz.ExtractComponent — Type
ExtractComponent(i; input=:default, output=Symbol("x", i))Filter extracting component i of a data array into a named scalar array.
FerriteViz.Magnitude — Type
Magnitude(; input=:default, output=:magnitude)Filter computing the euclidean norm of a data array into a named scalar array.
FerriteViz.Norm1 — Type
Norm1(; input=:default, output=:norm1)Filter computing the 1-norm of a data array into a named scalar array.
FerriteViz.VonMises — Type
VonMises(; input=:default, output=:vonMises)Filter computing the von Mises invariant (vonmises) of a tensor-valued data array into a named scalar array. Note that this is only a stress if the input array holds stresses — apply a constitutive law with Derive first when starting from a displacement gradient.
FerriteViz.Deviator — Type
Deviator(; input=:default, output=:deviator)Filter computing the deviatoric part of a tensor-valued data array.
FerriteViz.Threshold — Type
Threshold(; input=:default, output=:threshold, min=-Inf, max=Inf)Filter copying a data array with values outside [min, max] replaced by NaN.
This masks values, it does not remove geometry. The tessellation is passed through unchanged and the NaNs reach Makie as colors, so the affected triangles are still drawn — in nan_color (:red by default), and blended across a triangle whose other vertices are inside the range. Set nan_color=:transparent on the representation to hide them. Removing cells from the mesh is what CrinkleClip does.
FerriteViz.Derive — Type
Derive(f; input=:default, output=:derived)Generic derivation filter mapping the entries of one or more data arrays through f.
input is a single name or a vector of names. f receives one argument per input, taken from the same tessellation vertex (point data) or the same cell (cell data), so Derive(g; input=[:a, :b]) calls g(a_i, b_i). All inputs must be of the same kind, either all point data or all cell data.
Point-data rows are passed to f as a scalar (1 component), Vec (spatial-dim components) or Tensor{2} (spatial-dim² components). Rows holding a tensor of a different dimension than the grid — a shell or plane-strain problem carrying 3D stresses on a 2D grid — are recognised by their component count as Tensor{2,2} (4), SymmetricTensor{2,3} (6) or Tensor{2,3} (9). Cell-data entries are passed as-is. f may return a scalar, Vec, Tensor or Tuple.
Examples
σ(∇u) = 2G*dev(symmetric(∇u)) + K*tr(∇u)*one(∇u)
ds |> Gradient(:u) |> Derive(∇u -> vonmises(σ(∇u)); output=:σvM)
# several inputs -> one argument each
ds |> Derive((σ, εᵖ) -> σ ⊡ εᵖ; input=[:σ, :εᵖ], output=:dissipation)FerriteViz.vonmises — Function
vonmises(σ)Von Mises equivalent stress √(3/2 dev(σ) ⊡ dev(σ)) of a second-order tensor.
Representations
FerriteViz.solutionplot — Function
solutionplot(ds::FEData; kwargs...)
solutionplot(dh::AbstractDofHandler, u::Vector; kwargs...)
solutionplot!(...)Contour plot of a scalar data array on the finite element mesh.
color=:default: name of the field / point-data / cell-data array to color by.:defaultis the first field of the dof handler, reduced to its magnitude if vector-valued; an explicitly named array must be scalar — reduce with e.g.Magnitude()first. Anything that is not a data name is passed through to Makie as a plain color.colormap=:cividiscolorrange: (min, max) of the colorscale, automatic by default.shading=Makie.NoShadingnan_color=:red
Deformation is an upstream concern: solutionplot(ds |> WarpByVector(:u, 2.0)).
FerriteViz.cellplot — Function
cellplot(ds::FEData, values::Vector{<:Real}; kwargs...)
cellplot(ds::FEData; color=:name, kwargs...)
cellplot!(...)Plot one scalar per cell as constant color on the cells, either passed directly as a vector or by naming a registered cell-data array (see set_cell_data!). Non-scalar per-cell data (e.g. stress tensors) is reduced with a filter first (e.g. VonMises). Shares the solutionplot kwargs.
FerriteViz.meshplot — Function
meshplot(ds::FEData; kwargs...)
meshplot(grid::AbstractGrid; kwargs...)
meshplot!(...)Plot the finite element mesh (edges and nodes), optionally labeled. The wireframe is drawn from the dataset's tessellation edges, i.e. from the same vertices as the surface plots: it follows an upstream WarpByVector (including high-order and discontinuous deformation), is hidden with the cells a CrinkleClip removes, and bends along curved (high-order) cell edges according to the dataset's subdivision (see Refine).
Node markers and labels are drawn at the grid nodes of the visible cells; they are displaced by a warp only when the warp field is a dof field.
plotnodes=trueplot the nodes as circles/sphereslinewidthedge line widthcolorcolor of edges and nodesmarkersizesize of the nodescellsets=falsecolor cells by their cellset associationnodelabels=falseglobal node id labelsnodelabelcolor=:darkbluecelllabels=falseglobal cell id labelscelllabelcolor=:darkredfontsize=15label text sizevisible=true
FerriteViz.arrowplot — Function
arrowplot(ds::FEData; kwargs...)
arrowplot!(ds::FEData; kwargs...)Draw an arrow at every tessellation vertex for a vector-valued data array (only for spatial dim ≥ 2).
field=:defaultname of the vector data arraycolor=:defaultscalar data array name to color by, or a plain color;:defaultcolors by the vector magnitudenormalize=falsenormalize arrow lengthslengthscale=1f0scale arrow lengthscolormap=:cividis
FerriteViz.surfaceplot — Function
surfaceplot(ds::FEData{2}; kwargs...)
surfaceplot!(ds::FEData{2}; kwargs...)Plot a scalar data array of a 2D problem as a surface, with the value as the z-coordinate. color=:default names the array (same resolution rules as solutionplot, but it must be a data array).
FerriteViz.elementinfo — Function
elementinfo(ip::Interpolation; kwargs...)
elementinfo(cell::AbstractCell; kwargs...)
elementinfo(ip::Type{Interpolation}; kwargs...)
elementinfo(cell::Type{AbstractCell}; kwargs...)Plot the reference element with vertex/edge/face annotations; for a cell the geometry nodes are labeled "N", for an interpolation the dofs are labeled "D".
plotnodes=trueplot the nodeslinewidthstroke width of faces/edgescolormarkersizesize of the nodesfontsize=60fontsize of the labelsnodelabels=true,nodelabelcolor=:darkred,nodelabeloffset=(0.0,20.0)vertexlabels=true,vertexlabelcolor=:darkred,vertexlabeloffset=(0.0,0.0)edgelabels=true,edgelabelcolor=:darkblue,edgelabeloffset=(-40,-40)facelabels=true,facelabelcolor=:darkgreen,facelabeloffset=(-40,0)font="Julia Mono"
Composable viewer
The viewer is assembled declaratively with Makie.SpecApi: pluggable FerriteViz.Controls feed a view-state observable, a layout(ds, state) hook returns a GridLayoutSpec, and spec helpers build the panels.
FerriteViz.ferriteviewer — Function
ferriteviewer(ds::FEData; layout=default_layout, controls=default_controls(ds), pipeline=default_pipeline)
ferriteviewer(ds::FEData, u_history::Vector{<:Vector}; kwargs...)Interactive viewer composed declaratively with Makie.SpecApi. controls is a vector of Controls feeding a view-state observable; pipeline(ds, state) derives the dataset to plot (default applies deformation); layout(ds, state) returns the GridLayoutSpec rendered on every structural state change. All three are overridable — the defaults reproduce a single solutionplot panel with a colorbar. The second form appends a TimeSlider for a solution history.
Because plots pass the same ds and named data, structural changes reuse the existing plots (only attributes diff), while FerriteViz.update! and deformation stream through the shared GPU buffers without rebuilding.
FerriteViz.Control — Type
Control(make)A pluggable viewer control. make(fig, ds) builds its widget(s) and returns a ControlResult declaring the widgets and the view-state observables they contribute. Built-in controls: FieldMenu, ProcessMenu, ColormapMenu, LabelsToggle, DeformationToggle, TimeSlider.
FerriteViz.ControlResult — Type
ControlResult(content; structural=[], dynamic=[], placement=:column)Return value of a Control's builder. content is a vector of layoutables; placement decides where they go: :column (the right-hand controls column, default) or :below (each on its own full-width row under the plot — e.g. a TimeSlider). structural state pairs (name => Observable) trigger a spec rebuild when they change; dynamic state pairs are made available to the pipeline/layout but do not (they stream through the shared observables instead, e.g. a deformation scale).
FerriteViz.default_controls — Function
default_controls(ds) -> Vector{Control}The default control set: field/process/colormap menus, a wireframe toggle, a labels toggle and (if a field can deform the mesh) a deformation toggle. Override via the controls keyword of ferriteviewer.
FerriteViz.default_layout — Function
default_layout(ds, state) -> Makie.GridLayoutSpecThe default single-panel layout: a solutionplot colored by the selected field/process, a meshplot wireframe (shown/labeled per the wireframe and labels toggles), and a linked colorbar. Pass your own layout(ds, state) to ferriteviewer for any composition of panels and representations.
FerriteViz.default_pipeline — Function
default_pipeline(ds, state) -> FEDataBuild the dataset the default layout plots. Applies an observable-scale WarpByVector when a DeformationToggle contributed a :deform_scale (so the toggle deforms the mesh in place).
FerriteViz.FieldMenu — Function
FieldMenu(; label="field")Control selecting which dof field to color by (state :field).
FerriteViz.ProcessMenu — Function
ProcessMenu(; label="processing", options=["magnitude","x₁","x₂","x₃"])Control choosing the scalar reduction of the colored field (state :process).
FerriteViz.ColormapMenu — Function
ColormapMenu(; label="colormap", options=["cividis","inferno","thermal"])Control choosing the colormap (state :colormap, a Symbol).
FerriteViz.WireframeToggle — Function
WireframeToggle(; label="wireframe", active=true)Control toggling the mesh wireframe overlay (state :wireframe).
FerriteViz.LabelsToggle — Function
LabelsToggle(; label="labels", active=false)Control toggling node/cell id labels (state :labels).
FerriteViz.DeformationToggle — Function
DeformationToggle(; label="deformation", active=false)Control toggling warp-by-vector deformation (dynamic state :deform_scale; the scale streams through the shared observables without a spec rebuild).
FerriteViz.TimeSlider — Function
TimeSlider(u_history; label="timestep")Control stepping FerriteViz.update! through a solution history. Placed as a full-width slider below the plot (placement=:below). Purely side-effecting: it streams new solutions into the pipeline, contributing no structural state.
FerriteViz.panelspec — Function
panelspec(plots...; colorbar=nothing, dim=2, axis=(;), colorbar_attributes=(;))Assemble one or more PlotSpecs into a GridLayoutSpec of a single axis (an Axis for dim ≤ 2, an LScene otherwise), optionally with a linked Colorbar. Pass the PlotSpec to colorbar-link as colorbar (typically one of plots). axis is a NamedTuple of axis attributes.
FerriteViz.solutionplotspec — Function
solutionplotspec(ds; kwargs...) -> Makie.PlotSpecPlotSpec for a solutionplot, for use inside a layout hook / Makie.SpecApi. Analogous helpers exist for every representation: meshplotspec, cellplotspec, surfaceplotspec, arrowplotspec.
FerriteViz.meshplotspec — Function
meshplotspec(ds; kwargs...) -> Makie.PlotSpecFerriteViz.cellplotspec — Function
cellplotspec(ds; kwargs...) -> Makie.PlotSpecFerriteViz.surfaceplotspec — Function
surfaceplotspec(ds; kwargs...) -> Makie.PlotSpecFerriteViz.arrowplotspec — Function
arrowplotspec(ds; kwargs...) -> Makie.PlotSpec