Developer Documentation
Note that these functions could be removed or change in behavior between minor version changes! Use and dispatch on these with care!
Architecture
FerriteViz is structured in three layers, following the ParaView model:
- Tessellation (
src/tessellation.jl): every reference shape describes its surface triangulation and its wireframe edge segments with a singleFerriteViz.ReferenceTessellation— the edges are separate from the triangles because the triangulation contains interior diagonals that are not finite element edges.FEDatalays this out per cell with duplicated vertices, so discontinuous (L2) fields render with their inter-element jumps intact, and maps reference coordinates through the cell's geometric interpolation. High-order cells (or high-order fields) get their reference tessellation subdivided first (FerriteViz.subdivide, driven by theRefinefilter whose automatic modeFEDataapplies unless constructed withadaptive=false), so curved geometry and deformation render curved. Since the wireframe's vertices are ordinary tessellation vertices,meshplotinherits warping, clipping and refinement from the pipeline without any special-casing.src/qptessellation.jladds a second, quadrature rule dependent reference geometry: the Voronoi partition of a reference shape induced by its quadrature points, whichAddQuadraturePointDatauses to render internal variables piecewise constant. - Data pipeline (
src/dataset.jl,src/filters.jl):FEDataholds the solution as anObservableplus named point-/cell-data arrays; filters derive new datasets while sharing the source observable, soFerriteViz.update!propagates through the entire pipeline. The coordinates and triangles live inShaderAbstractions.Buffers shared into aGeometryBasics.Mesh— updates mutate GPU data in place without rebuilding. - Representations (
src/representations.jl): thin Makie recipes that take anFEDataand the name of the array to color by.
Adding support for a custom cell type
Implement one method. For a 3D reference shape, FerriteViz.facet_based_tessellation usually is all you need — e.g. if pyramids were not already supported, this would make FEData and all representations work for them:
FerriteViz.reference_tessellation(::Type{Ferrite.RefPyramid}) =
FerriteViz.facet_based_tessellation(Ferrite.RefPyramid)For 2D shapes, construct the FerriteViz.ReferenceTessellation directly (coordinates in reference space, triangles and wireframe edge segments indexing into them; shared coordinates are fine — per-cell duplication is FEData's job). Edges may be omitted, in which case meshplot draws no wireframe for cells of that shape.
Data layout
Point-data arrays are Matrix{Float64} (nvertices × ncomponents) with tensor components in Tensors.jl linear (column-major) order; scalars have one column. Cell-data arrays are per-cell Vectors of arbitrary element type.
Reference
FerriteViz.ReferenceTessellation — Type
ReferenceTessellation{refdim,T}Surface triangulation of a reference shape: coords are vertices in reference space, triangles index into coords. Coordinates may be shared between triangles; the per-cell vertex duplication that makes discontinuous (L2) fields render correctly is applied by FEData, not here.
edges are the wireframe segments drawn by meshplot: polylines along the finite element cell's edges (from Ferrite.reference_edges), also indexing into coords. They are deliberately separate from the triangles — the triangulation contains interior diagonals (e.g. the quadrilateral's center fan) that are not cell edges and must not show up in the wireframe. A tessellation without edges renders no wireframe.
FerriteViz.reference_tessellation — Function
reference_tessellation(::Type{<:Ferrite.AbstractRefShape}) -> ReferenceTessellationThe extension point for custom cell types: return the surface triangulation of the reference shape. Implementing this one method makes FEData and all representations work for cells with that reference shape. For 3D shapes, facet_based_tessellation builds a valid tessellation from Ferrite.reference_faces.
FerriteViz.facet_based_tessellation — Function
facet_based_tessellation(::Type{<:Ferrite.AbstractRefShape{3}}) -> ReferenceTessellationBuild the surface tessellation of a 3D reference shape from its faces: each face's 2D tessellation (triangle or quadrilateral, chosen by vertex count) is mapped into the element via Ferrite.facet_to_element_transformation. The wireframe edges come from Ferrite.reference_edges, with their own (duplicated) endpoint vertices appended after the face vertices. This is the default building block for reference_tessellation of volumetric shapes.
FerriteViz.subdivide — Function
subdivide(tess::ReferenceTessellation, n::Int) -> ReferenceTessellationSubdivide a tessellation in reference space, n times: every triangle into 4 (orientation preserving) and every edge segment into 2. Midpoints are deduplicated by coordinate, so subdivided triangles share vertices with their neighbours and with edge segments running along the same reference line. New vertices are appended, so indices into the input tessellation stay valid.
This is what resolves curved geometry: the subdivided reference vertices are mapped through the cell's geometric interpolation when the tessellation is instantiated by FEData, so surfaces and wireframe edges of high-order (or nonlinearly deformed) cells bend instead of being drawn as flat facets and straight chords.
FerriteViz.QPTessellation — Type
QPTessellation{refdim}Voronoi partition of a reference shape induced by a quadrature rule. coords are vertices in reference space, triangles index into them, and vertex_qp[v] is the quadrature point whose region vertex v belongs to.
Vertices are not shared between regions: every region carries its own copy, so assigning each vertex its quadrature point's value renders the region flat.
FerriteViz.qp_voronoi_tessellation — Function
qp_voronoi_tessellation(::Type{<:Ferrite.AbstractRefShape}, qr::Ferrite.QuadratureRule) -> QPTessellationPartition a reference shape into the Voronoi regions of qr's quadrature points and triangulate them. For 3D shapes the partition is intersected with the boundary faces, which is what the surface renderer draws.
FerriteViz.ntriangles — Function
Number of triangles a cell tessellates into.
FerriteViz.num_vertices — Function
Total number of tessellation vertices, i.e. vertices of the rendered triangulation. These are not the vertices of the finite element cells: cells do not share them (they are duplicated per cell, so discontinuities render), and a tessellated cell generally carries more of them than it has corners.
FerriteViz.transfer_solution — Function
transfer_solution(ds::FEData, u::Vector; field_name=:u) -> Matrix{Float64}Evaluate the field at every tessellation vertex of every visible cell from the owning element's dofs (preserving inter-element discontinuities). Vertices of invisible cells or cells outside the field's subdomain stay NaN.
FerriteViz.transfer_scalar_celldata — Function
transfer_scalar_celldata(ds::FEData, values::AbstractVector) -> Vector{Float64}Expand one scalar per cell to the tessellation vertices.
FerriteViz.interpolate_gradient_field — Function
interpolate_gradient_field(dh::DofHandler, u::AbstractVector, field_name::Symbol; copy_fields::Vector{Symbol})Compute the piecewise discontinuous gradient field for field_name. Returns the flux dof handler and the corresponding flux dof values. If the additional keyword argument copy_fields is provided with a non empty Vector{Symbol}, the corresponding fields of dh will be copied into the returned flux dof handler and flux dof value vector.
FerriteViz._tensorsjl_gradient_accessor — Function
_tensorsjl_gradient_accessor(v::Tensors.Vec, field_dim_idx::Int, spatial_dim_idx::Int)This is a helper to access the correct value in Tensors.jl entities, because the gradient index is the outermost one.