Degrees of freedom

Degrees of freedom (dofs) are distributed by the DofHandler.

Ferrite.DofHandlerType
DofHandler(grid::Grid)

Construct a DofHandler based on the grid grid.

After construction any number of discrete fields can be added to the DofHandler using add!. Construction is finalized by calling close!.

By default fields are added to all elements of the grid. Refer to SubDofHandler for restricting fields to subdomains of the grid.

Examples

dh = DofHandler(grid)ip_u = Lagrange{RefTriangle, 2}()^2 # vector interpolation for a field uip_p = Lagrange{RefTriangle, 1}()   # scalar interpolation for a field padd!(dh, :u, ip_u)add!(dh, :p, ip_p)close!(dh)
Numbering of degree of freedom

Note that the numbering of degrees of freedom do NOT follow the global numbering of nodes in the associated grid.

source
Ferrite.SubDofHandlerType
SubDofHandler(dh::AbstractDofHandler, cellset::AbstractVecOrSet{Int})

Create an sdh::SubDofHandler from the parent dh, pertaining to the cells in cellset. This allows you to add fields to parts of the domain, or using different interpolations or cell types (e.g. Triangles and Quadrilaterals). All fields and cell types must be the same in one SubDofHandler.

After construction any number of discrete fields can be added to the SubDofHandler using add!. Construction is finalized by calling close! on the parent dh.

Examples

We assume we have a grid containing "Triangle" and "Quadrilateral" cells, including the cellsets "triangles" and "quadrilaterals" for these cells.

dh = DofHandler(grid)sdh_tri = SubDofHandler(dh, getcellset(grid, "triangles"))ip_tri = Lagrange{RefTriangle, 2}()^2 # vector interpolation for a field uadd!(sdh_tri, :u, ip_tri)sdh_quad = SubDofHandler(dh, getcellset(grid, "quadilaterals"))ip_quad = Lagrange{RefQuadrilateral, 2}()^2 # vector interpolation for a field uadd!(sdh_quad, :u, ip_quad)close!(dh) # Finalize by closing the parent
source

Adding fields to the DofHandlers

Ferrite.add!Method
add!(dh::DofHandler, name::Symbol, ip::Interpolation)

Add a field called name approximated by ip to the DofHandler dh.

The field is added to all cells of the underlying grid, use SubDofHandlers if the grid contains multiple cell types, or to add the field to subset of all the cells.

source
Ferrite.close!Method
close!(dh::AbstractDofHandler)

Closes dh and creates degrees of freedom for each cell.

source

Algebraic variables and coupling descriptors

See the topic section on Algebraic variables.

Ferrite.AlgebraicVariableType
AlgebraicVariable()
AlgebraicVariable{V}()

Declaration of a typed algebraic (mesh-free) unknown that can be added to a DofHandler with add!. Its dofs are not attached to the mesh and do not appear in celldofs.

AlgebraicVariable() declares a scalar. Supported value shapes are Vec{dim}, Tensor{2, dim}, SymmetricTensor{2, dim}, Tensor{4, dim}, and SymmetricTensor{4, dim}, where dim is in 1:3. Every independent component of the value shape receives one dof; to prescribe individual components, use an AffineConstraint on the corresponding dof.

Examples

add!(dh, :p0, AlgebraicVariable())                            # one scalar unknownadd!(dh, :z, AlgebraicVariable{Vec{3}}())                     # three unknownsadd!(dh, :σ̄, AlgebraicVariable{SymmetricTensor{2, 2}}())      # three unknowns

See also AlgebraicValues and algebraic_value.

source
Ferrite.add!Method
add!(dh::DofHandler, name::Symbol, variable::AlgebraicVariable)

Add the algebraic (mesh-free) variable variable called name to the DofHandler dh.

Algebraic variables receive one global dof per independent component (see AlgebraicVariable), numbered after all spatial dofs in close!. They have no implicit mesh support: their dofs do not appear in celldofs, and coupling to spatial fields is declared explicitly with CellCoupling, FacetCoupling, and AlgebraicCoupling. Spatial fields and algebraic variables share one name namespace.

source
Ferrite.algebraic_valueFunction
algebraic_value(av::AlgebraicValues, u::AbstractVector, dof_range = eachindex(u))

Reconstruct the algebraic value from u[dof_range]. The scalar type follows eltype(u).

source
algebraic_value(dh::DofHandler, a::AbstractVector, name::Symbol)

Reconstruct the typed algebraic value name from the global solution vector a.

source
Ferrite.CellCouplingType
CellCoupling(cells; algebraic_coupling)

Structural descriptor for weak-form terms integrated over the cells in cells, coupling algebraic variables to spatial fields or other algebraic variables.

algebraic_coupling accepts entries involving at least one algebraic variable:

  • :u => :σ̄ declares a directional coupling: test dofs of :u may couple to trial dofs of :σ̄;
  • (:u, :σ̄) declares both directions at once.

A single entry may be passed bare, without the surrounding collection.

The descriptor is independent of any DofHandler: it only declares the coupling. The names are resolved when the descriptor is used, e.g. passed to the algebraic_couplings keyword argument of allocate_matrix.

See also FacetCoupling and AlgebraicCoupling.

source
Ferrite.FacetCouplingType
FacetCoupling(facets; algebraic_coupling)

Structural descriptor for weak-form terms integrated over the facets in facets (a set of FacetIndex). See CellCoupling for the keywords.

The local layout contains all dofs of each adjacent cell, since facet terms may use cell gradients.

source
Ferrite.AlgebraicCouplingType
AlgebraicCoupling(; algebraic_coupling)

Descriptor for terms involving only algebraic variables. See CellCoupling for the keywords. Since diagonal matrix entries are always allocated, this is only needed for off-diagonal entries.

source

DoF renumbering

Ferrite.renumber!Function
renumber!(dh::AbstractDofHandler, order)
renumber!(dh::AbstractDofHandler, ch::ConstraintHandler, order)

Renumber the degrees of freedom in the DofHandler and/or ConstraintHandler according to the ordering order.

order can be given by one of the following options:

  • A permutation vector perm::AbstractVector{Int} such that dof i is renumbered to perm[i].
  • DofOrder.FieldWise() for renumbering dofs field wise.
  • DofOrder.ComponentWise() for renumbering dofs component wise.
  • DofOrder.Ext{T} for "external" renumber permutations, see documentation for DofOrder.Ext for details.
Warning

The dof numbering in the DofHandler and ConstraintHandler must always be consistent. It is therefore necessary to either renumber before creating the ConstraintHandler in the first place, or to renumber the DofHandler and the ConstraintHandler together.

source
Ferrite.DofOrder.FieldWiseType
DofOrder.FieldWise()
DofOrder.FieldWise(target_blocks::Vector{Int})

Dof order passed to renumber! to renumber global dofs field wise resulting in a globally blocked system.

The default behavior is to group dofs of each field into their own block, with the same order as in the DofHandler. This can be customized by passing a vector of the same length as the total number of fields in the DofHandler (see getfieldnames(dh)) that maps each field to a "target block": to renumber a DofHandler with three fields :u, :v, :w such that dofs for :u and :w end up in the first global block, and dofs for :v in the second global block use DofOrder.FieldWise([1, 2, 1]).

Algebraic variables count as fields here: they follow after all spatial fields, in declaration order, and target_blocks (if passed) must include entries for them.

This renumbering is stable such that the original relative ordering of dofs within each target block is maintained.

source
Ferrite.DofOrder.ComponentWiseType
DofOrder.ComponentWise()
DofOrder.ComponentWise(target_blocks::Vector{Int})

Dof order passed to renumber! to renumber global dofs component wise resulting in a globally blocked system.

The default behavior is to group dofs of each component into their own block, with the same order as in the DofHandler. This can be customized by passing a vector of length ncomponents that maps each component to a "target block" (see DofOrder.FieldWise for details).

Each component of an algebraic variable counts as one component here, following after all spatial components.

This renumbering is stable such that the original relative ordering of dofs within each target block is maintained.

source

Common methods

Ferrite.ndofsFunction
ndofs(dh::AbstractDofHandler)

Return the number of degrees of freedom in dh

source
Ferrite.ndofs_per_cellFunction
ndofs_per_cell(dh::AbstractDofHandler[, cell::Int=1])

Return the number of degrees of freedom for the cell with index cell.

See also ndofs.

source
Ferrite.dof_rangeFunction
dof_range(sdh::SubDofHandler, field_idx::Int)
dof_range(sdh::SubDofHandler, field_name::Symbol)
dof_range(dh:DofHandler, field_name::Symbol)

Return the local dof range for a given field. The field can be specified by its name or index, where field_idx represents the index of a field within a SubDofHandler and field_idxs is a tuple of the SubDofHandler-index within the DofHandler and the field_idx.

Note

The dof_range of a field can vary between different SubDofHandlers. Therefore, it is advised to use the field_idxs or refer to a given SubDofHandler directly in case several SubDofHandlers exist. Using the field_name will always refer to the first occurrence of field within the DofHandler.

Example:

julia> grid = generate_grid(Triangle, (3, 3))Grid{2, Triangle, Float64} with 18 Triangle cells and 16 nodesjulia> dh = DofHandler(grid); add!(dh, :u, 3); add!(dh, :p, 1); close!(dh);julia> dof_range(dh, :u)1:9julia> dof_range(dh, :p)10:12julia> dof_range(dh, (1, 1)) # field :u1:9julia> dof_range(dh.subdofhandlers[1], 2) # field :p10:12
source
Ferrite.celldofsFunction
celldofs(dh::AbstractDofHandler, i::Int)

Return a vector with the degrees of freedom that belong to cell i.

See also celldofs!.

source
Ferrite.celldofs!Function
celldofs!(global_dofs::Vector{Int}, dh::AbstractDofHandler, i::Int)

Store the degrees of freedom that belong to cell i in global_dofs.

See also celldofs.

source

Grid iterators

Ferrite.CellCacheType
CellCache(grid::Grid)
CellCache(dh::AbstractDofHandler)

Create a cache object with pre-allocated memory for the nodes, coordinates, and dofs of a cell. The cache is updated for a new cell by calling reinit!(cache, cellid) where cellid::Int is the cell id.

Methods with CellCache

  • reinit!(cc, i): reinitialize the cache for cell i
  • cellid(cc): get the cell id of the currently cached cell
  • getnodes(cc): get the global node ids of the cell
  • getcoordinates(cc): get the coordinates of the cell
  • celldofs(cc): get the global dof ids of the cell
  • reinit!(fev, cc): reinitialize CellValues or FacetValues

See also CellIterator.

source
Ferrite.CellIteratorType
CellIterator(grid::Grid, cellset = 1:getncells(grid))
CellIterator(dh::AbstractDofHandler, cellset = 1:getncells(dh))

Create a CellIterator to conveniently iterate over all, or a subset, of the cells in a grid. The elements of the iterator are CellCaches which are properly reinit!ialized. See CellCache for more details.

Looping over a CellIterator, i.e.:

for cc in CellIterator(grid, cellset)    # ...end

is thus simply convenience for the following equivalent snippet:

cc = CellCache(grid)for idx in cellset    reinit!(cc, idx)    # ...end
Warning

CellIterator is stateful and should not be used for things other than for-looping (e.g. broadcasting over, or collecting the iterator may yield unexpected results).

source
Ferrite.FacetCacheType
FacetCache(grid::Grid)
FacetCache(dh::AbstractDofHandler)

Create a cache object with pre-allocated memory for the nodes, coordinates, and dofs of a cell suitable for looping over facets in a grid. The cache is updated for a new facet by calling reinit!(cache, fi::FacetIndex).

Methods with fc::FacetCache

  • reinit!(fc, fi): reinitialize the cache for facet fi::FacetIndex
  • cellid(fc): get the current cellid
  • getnodes(fc): get the global node ids of the cell
  • getcoordinates(fc): get the coordinates of the cell
  • celldofs(fc): get the global dof ids of the cell
  • reinit!(fv, fc): reinitialize FacetValues

See also FacetIterator.

source
Ferrite.FacetIteratorType
FacetIterator(gridordh::Union{Grid, AbstractDofHandler}, facetset::AbstractVecOrSet{FacetIndex})

Create a FacetIterator to conveniently iterate over the faces in facetset. The elements of the iterator are FacetCaches which are properly reinit!ialized. See FacetCache for more details.

Looping over a FacetIterator, i.e.:

for fc in FacetIterator(grid, facetset)    # ...end

is thus simply convenience for the following equivalent snippet:

fc = FacetCache(grid)for faceindex in facetset    reinit!(fc, faceindex)    # ...end
source
Ferrite.InterfaceCacheType
InterfaceCache(grid::Grid)
InterfaceCache(dh::AbstractDofHandler)

Create a cache object with pre-allocated memory for the nodes, coordinates, and dofs of an interface. The cache is updated for a new cell by calling reinit!(cache, facet_a, facet_b) where facet_a::FacetIndex and facet_b::FacetIndex are the two interface facets.

Struct fields of InterfaceCache

  • ic.a :: FacetCache: facet cache for the first facet of the interface
  • ic.b :: FacetCache: facet cache for the second facet of the interface
  • ic.dofs :: Vector{Int}: global dof ids for the interface (union of ic.a.dofs and ic.b.dofs)

Methods with InterfaceCache

  • reinit!(cache::InterfaceCache, facet_a::FacetIndex, facet_b::FacetIndex): reinitialize the cache for a new interface
  • interfacedofs(ic): get the global dof ids of the interface

See also InterfaceIterator.

source
Ferrite.InterfaceIteratorType
InterfaceIterator(grid::Grid, [topology::ExclusiveTopology])
InterfaceIterator(dh::AbstractDofHandler, [topology::ExclusiveTopology])

Create an InterfaceIterator to conveniently iterate over all the interfaces in a grid. The elements of the iterator are InterfaceCaches which are properly reinit!ialized. See InterfaceCache for more details. Looping over an InterfaceIterator, i.e.:

for ic in InterfaceIterator(grid, topology)    # ...end

is thus simply convenience for the following equivalent snippet for grids of dimensions > 1:

ic = InterfaceCache(grid)neighborhood = Ferrite.get_facet_facet_neighborhood(topology, grid)for facet in facetskeleton(topology, grid)    neighbors = neighborhood[facet[1], facet[2]]    isempty(neighbors) && continue    neighbor_facet = neighbors[1]    reinit!(ic, facet, neighbor_facet)    # ...end
Warning

InterfaceIterator is stateful and should not be used for things other than for-looping (e.g. broadcasting over, or collecting the iterator may yield unexpected results).

source