Grid

Grid

Ferrite.generate_grid — Function
generate_grid(celltype::Cell, nel::NTuple, [left::Vec, right::Vec)

Return a Grid for a rectangle in 1, 2 or 3 dimensions. celltype defined the type of cells, e.g. Triangle or Hexahedron. nel is a tuple of the number of elements in each direction. left and right are optional endpoints of the domain. Defaults to -1 and 1 in all directions.

source
Ferrite.Node — Type
Node{dim, T}

A Node is a point in space.

Fields

  • x::Vec{dim,T}: stores the coordinates
source
Ferrite.CellIndex — Type
CellIndex(cellid::Int)

A CellIndex wraps an Int and corresponds to a cell with that number in the mesh.

source
Ferrite.VertexIndex — Type
VertexIndex(cellid::Int, vertexid::Int)

A VertexIndex wraps an (Int, Int) and defines a local vertex by pointing to a (cell, vert).

source
Ferrite.EdgeIndex — Type
EdgeIndex(cellid::Int, edgeid::Int)

An EdgeIndex wraps an (Int, Int) and defines a local edge by pointing to a (cell, edge).

source
Ferrite.FaceIndex — Type
FaceIndex(cellid::Int, faceid::Int)

A FaceIndex wraps an (Int, Int) and defines a local face by pointing to a (cell, face).

source
Ferrite.FacetIndex — Type
FacetIndex(cellid::Int, facetid::Int)

A FacetIndex wraps an (Int, Int) and defines a local facet by pointing to a (cell, facet).

source
Ferrite.Grid — Type
Grid{dim, C<:AbstractCell, T<:Real} <: AbstractGrid}

A Grid is a collection of Ferrite.AbstractCells and Ferrite.Nodes which covers the computational domain. Helper structures for applying boundary conditions or define subdomains are gathered in cellsets, nodesets, facetsets, and vertexsets.

Fields

  • cells::Vector{C}: stores all cells of the grid
  • nodes::Vector{Node{dim,T}}: stores the dim dimensional nodes of the grid
  • cellsets::Dict{String, OrderedSet{Int}}: maps a String key to an OrderedSet of cell ids
  • nodesets::Dict{String, OrderedSet{Int}}: maps a String key to an OrderedSet of global node ids
  • facetsets::Dict{String, OrderedSet{FacetIndex}}: maps a String to an OrderedSet of FacetIndex
  • vertexsets::Dict{String, OrderedSet{VertexIndex}}: maps a String key to an OrderedSet of VertexIndex
source

Utility functions

Ferrite.getcells — Function
getcells(forest::ForestBWG) -> Vector{OctantBWG}

Collect the leaf octants of all trees of forest into a single vector, in ascending cell id order (tree by tree, Morton order within each tree) — i.e. the octant getcells(forest)[i] materializes into cell i of creategrid(forest).

Allocates on every call

This materializes a fresh vector of all leaves each time it is called — O(n) in the number of cells. Call it once and reuse the result instead of calling it inside loops.

The returned octants live in the coordinate system of their respective tree, so the scalar getcells(forest, cellid) from the AbstractGrid interface is deliberately not supported (an octant is not interpretable without its tree) and throws instead of falling back to forest.cells[cellid], which would inconsistently return a whole tree. Take forest.cells[k].leaves for tree-local work.

source
getcells(grid::AbstractGrid)
getcells(grid::AbstractGrid, v::Union{Integer, AbstractVector{<:Integer}}
getcells(grid::AbstractGrid, setname::String)

Returns either all cells::Collection{C<:AbstractCell} of a <:AbstractGrid or a subset based on an Int, Vector{Int} or String. Whereas the last option tries to call a cellset of the grid. Collection can be any indexable type, for Grid it is Vector{C<:AbstractCell}.

source
Ferrite.getnodes — Function
getnodes(grid::AbstractGrid)
getnodes(grid::AbstractGrid, v::Union{Integer, AbstractVector{<:Integer}}
getnodes(grid::AbstractGrid, setname::String)

Returns either all nodes::Collection{N} of a <:AbstractGrid or a subset based on an Integer, AbstractVector{<:Integer} or String. The last option tries to call a nodeset of the <:AbstractGrid. Collection{N} refers to some indexable collection where each element corresponds to a Node.

source
Ferrite.getcellset — Function
getcellset(grid::AbstractGrid, setname::String)

Returns all cells as cellid in the set with name setname.

source
Ferrite.getnodeset — Function
getnodeset(grid::AbstractGrid, setname::String)

Returns all nodes as nodeid in the set with name setname.

source
Ferrite.getfacetset — Function
getfacetset(grid::AbstractGrid, setname::String)

Returns all facets as FacetIndex in the set with name setname.

source
Ferrite.getvertexset — Function
getvertexset(grid::AbstractGrid, setname::String)

Returns all vertices as VertexIndex in the set with name setname.

source
Ferrite.transform_coordinates! — Function
transform_coordinates!(grid::Abstractgrid, f::Function)

Transform the coordinates of all nodes of the grid based on some transformation function f(x).

source
Ferrite.getcoordinates! — Function
getcoordinates!(x::Vector{<:Vec}, grid::AbstractGrid, idx::Union{Int, CellIndex})
getcoordinates!(x::Vector{<:Vec}, grid::AbstractGrid, cell::AbstractCell)

Mutate x to the coordinates of the cell corresponding to idx or cell.

source
Ferrite.geometric_interpolation — Method
geometric_interpolation(::AbstractCell)::ScalarInterpolation
geometric_interpolation(::Type{<:AbstractCell})::ScalarInterpolation

Each AbstractCell type has a unique geometric interpolation describing its geometry. This function returns that interpolation, which is always a scalar interpolation.

source
Ferrite.getspatialdim — Method
Ferrite.getspatialdim(grid::AbstractGrid)

Get the spatial dimension of the grid, corresponding to the vector dimension of the grid's coordinates.

source
Ferrite.getrefdim — Method
Ferrite.getrefdim(cell::AbstractCell)
Ferrite.getrefdim(::Type{<:AbstractCell})

Get the reference dimension of the cell, i.e. the dimension of the cell's reference shape.

source

Topology

Ferrite.ExclusiveTopology — Type
ExclusiveTopology(grid::AbstractGrid)

The experimental feature ExclusiveTopology saves topological (connectivity/neighborhood) data of the grid. Only the highest dimensional neighborhood is saved. I.e., if something is connected by a face and an edge, only the face neighborhood is saved. The lower dimensional neighborhood is recomputed when calling getneighborhood if needed.

Fields

  • vertex_to_cell::AbstractArray{AbstractVector{Int}, 1}: global vertex id to all cells containing the vertex
  • cell_neighbor::AbstractArray{AbstractVector{Int}, 1}: cellid to all connected cells
  • face_neighbor::AbstractArray{AbstractVector{FaceIndex}, 2}: face_neighbor[cellid, local_face_id] -> neighboring faces
  • edge_neighbor::AbstractArray{AbstractVector{EdgeIndex}, 2}: edge_neighbor[cellid, local_edge_id] -> neighboring edges
  • vertex_neighbor::AbstractArray{AbstractVector{VertexIndex}, 2}: vertex_neighbor[cellid, local_vertex_id] -> neighboring vertices
  • face_skeleton::Union{Vector{FaceIndex}, Nothing}: List of unique faces in the grid given as FaceIndex
  • edge_skeleton::Union{Vector{EdgeIndex}, Nothing}: List of unique edges in the grid given as EdgeIndex
  • vertex_skeleton::Union{Vector{VertexIndex}, Nothing}: List of unique vertices in the grid given as VertexIndex

Grids with mixed reference dimensions (e.g. a 3D grid containing both Hexahedron and Quadrilateral cells) are supported: the shared entity is classified by the number of shared vertices, so mixed-dimensional connections are stored in vertex_vertex_neighbor, edge_edge_neighbor, or face_face_neighbor accordingly. Per-entity queries with VertexIndex, EdgeIndex, FaceIndex, and FacetIndex work for such grids (the facet dimension is resolved per cell). Please remember that the dimensions of faces (dim=2) and edges (dim=1) are fixed, i.e. they are defined independent of the spatial dimension of the grid. You can consult the entity naming page for details. The bulk operations facetskeleton and get_facet_facet_neighborhood remain unsupported, since they assume a common facet dimension across the whole grid.

Limitations

The implementation only works with conforming grids, i.e. grids without "hanging nodes". Non-conforming grids will give unexpected results. Purely embedded grids, where the highest cell reference dimension is smaller than the spatial dimension (e.g. a shell grid of Quadrilaterals in 3D space), are not supported and will error on construction.

source
Ferrite.getneighborhood — Function
getneighborhood(topology, grid::AbstractGrid, cellidx::CellIndex, include_self = false)
getneighborhood(topology, grid::AbstractGrid, faceidx::FaceIndex, include_self = false)
getneighborhood(topology, grid::AbstractGrid, vertexidx::VertexIndex, include_self = false)
getneighborhood(topology, grid::AbstractGrid, edgeidx::EdgeIndex, include_self = false)

Returns all connected entities of the same type as defined by the respective topology. If include_self is true, the given entity is included in the returned list as well.

source
Ferrite.facetskeleton — Function
facetskeleton(forest::ForestBWG{dim}) -> Vector{NTuple{2, FacetIndex}}

Materialize the interior facet skeleton of the refined forest. The skeleton holds one entry per leaf-level facet interface, as a pair of FacetIndex into the grid returned by creategrid (the cell numbering is identical — tree by tree, leaves in Morton order). For a conforming interface the pair holds the two equal-size cells sharing the facet. For a non-conforming (hanging) interface each fine subfacet gets its own pair, fine side first and the coarse cell's facet second — the orientation facet-jump (Kelly-type) error estimators integrate: over the fine subfacet, evaluating the neighbour on the coarse side.

Domain-boundary facets are not part of the skeleton: a FacetIndex of the materialized grid that appears in no pair lies on the domain boundary, so the boundary is recovered by a complement sweep over all cell facets.

In contrast to facetskeleton(::ExclusiveTopology, ::AbstractGrid), this adjacency cannot be reconstructed from the materialized grid's topology — ExclusiveTopology only knows conforming neighbourhoods, while the true adjacency of the refined forest contains coarse↔fine (hanging) and across-tree interfaces. It is instead read off the forest: one face-only iterate_points traversal per tree (mindim = maxdim = dim - 1, FacetSkeletonVisitor) covers the intra-tree interfaces, and a two-sided lock-step descent of every shared tree face (_iter_interface_facets!) the inter-tree ones — the same primitives creategrid uses for node numbering and hanging-constraint detection.

Requires a 2:1-balanced forest (see balanceforest!), like creategrid.

source
facetskeleton(top::ExclusiveTopology, grid::AbstractGrid)

Materializes the skeleton from the neighborhood information by returning an iterable over the unique facets in the grid, described by FacetIndex.

source
Ferrite.interfaceskeleton — Function
interfaceskeleton(top::ExclusiveTopology, grid::AbstractGrid)

Materializes the interfaces of the grid (the interior facets, i.e. facets shared between two cells) as a Vector of facet pairs (facet_here, facet_there), where both facets are described by FacetIndex.

This is the subset of facetskeleton that excludes boundary facets, with the neighboring facet attached to each entry. The enumeration order matches the order in which InterfaceIterator visits the interfaces, and subsets of the returned vector can be iterated with InterfaceIterator(grid_or_dh, subset), e.g. for multithreaded assembly of interface terms (see create_coloring).

Like facetskeleton the result is cached in the topology, so repeated calls return the same vector (which therefore must not be modified).

source

Grid sets utility

Ferrite.addcellset! — Function
addcellset!(grid::AbstractGrid, name::String, cellid::AbstractVecOrSet{Int})
addcellset!(grid::AbstractGrid, name::String, f::function; all::Bool=true)

Adds a cellset to the grid with key name. Cellsets are typically used to define subdomains of the problem, e.g. two materials in the computational domain. The DofHandler can construct different fields which live not on the whole domain, but rather on a cellset. all=true implies that f(x) must return true for all nodal coordinates x in the cell if the cell should be added to the set, otherwise it suffices that f(x) returns true for one node.

addcellset!(grid, "left", Set((1, 3))) #add cells with id 1 and 3 to cellset leftaddcellset!(grid, "right", x -> norm(x[1]) < 2.0) #add cell to cellset right, if x[1] of each cell's node is smaller than 2.0
source
Ferrite.addfacetset! — Function
addfacetset!(grid::AbstractGrid, name::String, faceid::AbstractVecOrSet{FacetIndex})
addfacetset!(grid::AbstractGrid, name::String, f::Function; all::Bool = true)

Adds a facetset to the grid with key name. A facetset maps a String key to a OrderedSet of tuples corresponding to (global_cell_id, local_facet_id). Facetsets can be used to initialize Dirichlet boundary conditions for the ConstraintHandler. all=true implies that f(x) must return true for all nodal coordinates x on the facet if the facet should be added to the set, otherwise it suffices that f(x) returns true for one node.

addfacetset!(grid, "right", Set((FacetIndex(2, 2), FacetIndex(4, 2)))) #see grid manual example for referenceaddfacetset!(grid, "clamped", x -> norm(x[1]) ≈ 0.0) #see incompressible elasticity example for reference
source
Ferrite.addboundaryfacetset! — Function

addboundaryfacetset!(grid::AbstractGrid, topology::ExclusiveTopology, name::String, f::Function; all::Bool=true)

Adds a boundary facetset to the grid with key name. A facetset maps a String key to a OrderedSet of tuples corresponding to (global_cell_id, local_facet_id). Facetsets are used to initialize Dirichlet structs, that are needed to specify the boundary for the ConstraintHandler. all=true implies that f(x) must return true for all nodal coordinates x on the facet if the facet should be added to the set, otherwise it suffices that f(x) returns true for one node.

source
Ferrite.addvertexset! — Function
addvertexset!(grid::AbstractGrid, name::String, faceid::AbstractVecOrSet{FaceIndex})
addvertexset!(grid::AbstractGrid, name::String, f::Function)

Adds a vertexset to the grid with key name. A vertexset maps a String key to a OrderedSet of tuples corresponding to (global_cell_id, local_vertex_id). Vertexsets can be used to initialize Dirichlet boundary conditions for the ConstraintHandler.

addvertexset!(grid, "right", Set((VertexIndex(2, 2), VertexIndex(4, 2))))addvertexset!(grid, "clamped", x -> norm(x[1]) ≈ 0.0)
source
Ferrite.addboundaryvertexset! — Function

addboundaryvertexset!(grid::AbstractGrid, topology::ExclusiveTopology, name::String, f::Function; all::Bool=true)

Adds a boundary vertexset to the grid with key name. A vertexset maps a String key to an OrderedSet of tuples corresponding to (global_cell_id, local_vertex_id). all=true implies that f(x) must return true for all nodal coordinates x on the facet if the facet should be added to the set, otherwise it suffices that f(x) returns true for one node.

source
Ferrite.addnodeset! — Function
addnodeset!(grid::AbstractGrid, name::String, nodeid::AbstractVecOrSet{Int})
addnodeset!(grid::AbstractGrid, name::String, f::Function)

Adds a nodeset::OrderedSet{Int} to the grid's nodesets with key name. Has the same interface as addcellset. However, instead of mapping a cell id to the String key, a set of node ids is returned.

source

Multithreaded assembly

Ferrite.create_coloring — Function
create_coloring(
    grid::AbstractGrid, set = 1:getncells(grid);
    alg::ColoringAlgorithm
)

Create a coloring of the items in set such that no two conflicting items – items whose (concurrent) assembly may write to the same entries of the global matrix and vector – have the same color. The returned colors partition set, and all items of one color can therefore be assembled concurrently.

The items to color are determined by the element type of set:

  • cells (Int), e.g. a cellset (default: all cells of the grid). A cell writes to the dofs of the cell.
  • facets (FacetIndex), e.g. a facetset for assembly of boundary terms. A facet writes to the dofs of its cell.
  • interfaces (NTuple{2, FacetIndex}), e.g. interfaceskeleton or a subset of it for assembly of interface terms in DG methods. An interface writes to the dofs of its two cells.

Returns a vector of vectors of items, e.g. for cells:

ret = [   [1, 3, 5, 10, ...], # cells for color 1   [2, 4, 6, 12, ...], # cells for color 2]

The colors are processed one after another, with the items of each color distributed over concurrent tasks. See the multithreaded assembly how-to for complete examples.

The coloring is conservative: two items conflict if a cell of one shares a node with (or is equal to) a cell of the other, which is safe for any discretization (continuous fields place dofs on vertices, edges, and faces, shared with all node neighbors of the cell). Conflicts are only considered among the items in set, since only these are assembled by the corresponding loop. Duplicate cells in a cellset are ignored, while facets and interfaces must appear at most once in set (and interfaces in one orientation).

For an exact coloring, based on the dofs that the items write to, use create_coloring(dh::DofHandler, [ch], set) instead. This typically results in fewer colors, e.g. for discontinuous fields or fields with dofs on facets or edges only, and can also account for constraint condensation during assembly (apply_assemble!) of affine constraints (e.g. PeriodicDirichlet), which writes outside of the item dofs. This function is equivalent to create_coloring(AssemblyConflicts(grid), set; alg); construct the AssemblyConflicts explicitly to reuse them when coloring multiple sets (e.g. both the cells and the interfaces).

Two different algorithms are available, specified with the alg keyword argument:

  • alg = ColoringAlgorithm.WorkStream (default): Three step algorithm from Turcksin et al. [15], albeit with a greedy coloring in the second step. Generally results in more colors than ColoringAlgorithm.Greedy, however the items are more equally distributed among the colors.
  • alg = ColoringAlgorithm.Greedy: greedy algorithm that works well for structured quadrilateral grids such as e.g. quadrilateral grids from generate_grid.

The resulting cell colors can be visualized using Ferrite.write_cell_colors.

Cell to color mapping

In a previous version of Ferrite this function returned a dictionary mapping cell ID to color numbers as the first argument. If you need this mapping you can create it using the following construct:

colors = create_coloring(...)cell_colormap = Dict{Int,Int}(    cellid => color for (color, cellids) in enumerate(final_colors) for cellid in cellids)

References

  • [15] Turcksin et al. ACM Trans. Math. Softw. 43 (2016).
source
create_coloring(conflicts::AssemblyConflicts, set = 1:getncells(grid); alg::ColoringAlgorithm)

Create a coloring of the items (cells, facets, or interfaces, see create_coloring(::AbstractGrid)) in set from the precomputed conflicts (see AssemblyConflicts). An item writes to its cells (facets to the cell of the facet, and interfaces to the two cells of the interface), and two items conflict if they write to a common cell or to two conflicting cells. The same AssemblyConflicts can be reused to color multiple sets, e.g. both the cells and the interfaces.

source
create_coloring(
    dh::DofHandler, [ch::ConstraintHandler], set = 1:getncells(grid);
    alg::ColoringAlgorithm
)

Create a coloring of the items (cells, facets, or interfaces, see create_coloring(::AbstractGrid)) in set based on the dofs that the items write to. This is equivalent to create_coloring(AssemblyConflicts(dh, [ch]), set; alg), see AssemblyConflicts and create_coloring(::AssemblyConflicts); construct the AssemblyConflicts explicitly to reuse them when coloring multiple sets.

The resulting coloring is exact (two items conflict if and only if their assembly writes to a common dof), and therefore typically results in fewer colors than the grid based coloring, e.g. for discretizations where neighboring cells only share dofs on facets or edges (e.g. Nedelec or CrouzeixRaviart), or no dofs at all (e.g. DiscontinuousLagrange, in which case the cells need a single color). If the ConstraintHandler ch is given, writes to the master dofs of affinely constrained dofs are accounted for, which is required for constraint condensation during assembly (see apply_assemble!).

Note that algebraic dofs (see algebraic_dofs) are not part of the cell dofs, and writes to them are therefore not accounted for. Since they are typically shared by all cells, use atomic assembly for those instead.

source
Ferrite.AssemblyConflicts — Type
AssemblyConflicts(grid::AbstractGrid)
AssemblyConflicts(dh::DofHandler, [ch::ConstraintHandler])

Precompute the conflicts between the cells of the grid for coloring assembly loops. Two cells conflict if their assembly may write to a common entry of the global matrix and vector. The conflicts are used to compute colorings of cells, facets, and interfaces with create_coloring(::AssemblyConflicts, set), and the same AssemblyConflicts can be reused for coloring multiple sets (e.g. the cells, a facetset and the interfaces).

  • AssemblyConflicts(grid): conservative conflicts from the grid only: two cells conflict if they share a node (cf. create_coloring(::AbstractGrid)).
  • AssemblyConflicts(dh, [ch]): exact conflicts from the dofs: two cells conflict if they write to a common dof. The write set of a cell is given by its dofs (celldofs). If the ConstraintHandler ch is given the write set also includes the master dofs of the affinely constrained dofs of the cell, since constraint condensation during assembly (apply_assemble!) writes to these.
source