DofManager

The DofManager is a struct that keeps track of which dofs are unknown or constrained. This can work with simple or mixed finite element spaces of various types. It is a glorified book keeper.

A DofManager can be created as follows. First we must create functions for our variables of interest from their associated function spaces.

julia> using FiniteElementContainers
julia> mesh = UnstructuredMesh("../../test/poisson/poisson.g")UnstructuredMesh: Number of dimensions = 2 Number of nodes = 16641 Element Blocks: block_1: Element type = "block_1" => "QUAD4" Number of elements = 16384 Node sets: nset_4: Number of nodes = 129 nset_2: Number of nodes = 129 nset_3: Number of nodes = 129 nset_1: Number of nodes = 129 Side sets: sset_2: Number of elements = 128 sset_1: Number of elements = 128 sset_3: Number of elements = 128 sset_4: Number of elements = 128
julia> V = FunctionSpace(mesh, H1Field, Lagrange)FunctionSpace: Type: H1Field block_1:
julia> u = VectorFunction(V, "u")VectorFunction: names: ("u_x", "u_y")
julia> t = ScalarFunction(V, "t")ScalarFunction: names: ("t",)
julia> f = FiniteElementContainers.GeneralFunction(u, t)GeneralFunction: names: ("u_x", "u_y", "t")

Now we can supply these variables to the DofManager which takes varargs as inputs

julia> dof = DofManager(f)DofManager
  Number of entities        = 16641
  Number of dofs per entity = 3
  Number of total dofs      = 49923
  Number of dirichlet dofs  = 0
  Number of periodic dofs   = 0
  Number of unknown dofs    = 49923
  Storage type              = Vector{Int64}

The print methods for this struct show simple metadata about the current dofs for each possible function space.

A set of unknowns can be set up as follows

julia> field = create_unknowns(dof)49923-element Vector{Float64}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 ⋮
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0

We can create fields of the right size from the DofManager with the following methods

julia> field = create_field(dof)3×16641 H1Field{Float64, Vector{Float64}, 3}:
 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0

These methods take the backend of dof into account to ensure that the fields or unknowns produced are on the same device, e.g. CPU/GPU if dof is on the CPU/GPU.

This struct is created with all dofs initially set as unknown. To modify the unknowns we can do the following

API

FiniteElementContainers.DofManagerType
struct DofManager{Condensed, IT, IDs<:AbstractArray{IT, 1}, Var<:FiniteElementContainers.AbstractFunction} <: FiniteElementContainers.AbstractDofManager{IT, IDs<:AbstractArray{IT, 1}}
  • dirichlet_dofs::AbstractVector

  • dof_to_unknown::AbstractVector

  • periodic_side_a_dofs::AbstractVector

  • periodic_side_b_dofs::AbstractVector

  • periodic_side_b_to_side_a_unknown::AbstractVector

  • unknown_dofs::AbstractVector

  • var::FiniteElementContainers.AbstractFunction

source
Base.lengthMethod
length(dof::DofManager) -> Any

Return the total lenth of dofs in the problem.

E.g. for an H1 space this will the number of nodes times the number of degrees of freedom per node.

source
Base.sizeMethod
size(dof::DofManager, i::Int64) -> Any

size(dof, 1) returns the number of dofs per entity, and size(dof, 2) returns the number of entities.

source
Base.sizeMethod
size(dof::DofManager) -> Tuple{Any, Any}

This returns (n_dofs, n_entities) where n_dofs is the number of dofs per entity (e.g. node) and n_entities is the number of entitities (e.g. node).

source
FiniteElementContainers.create_fieldMethod
create_field(dof::DofManager) -> H1Field
create_field(
    dof::DofManager,
    float_type::Type{RT<:Number}
) -> H1Field

Creates a field where typeof(field) <: AbstractField based on the variable dof was created with

source
FiniteElementContainers.create_unknownsMethod
create_unknowns(dof::DofManager{Flag, IT, IDs, Var}) -> Any
create_unknowns(
    dof::DofManager{Flag, IT, IDs, Var},
    float_type
) -> Any

Creates a vector of unknown dofs.

The backend of $dof$ will be used as the backend for the generated array.

There is an optional argument $float_type$ that defaults to $Float64$.

source
FiniteElementContainers.dof_to_unknown_indexMethod

Map a single global DOF index to its reduced unknown index.

  • Returns -1 for Dirichlet DOFs (caller should skip these).
  • Returns the sidea's unknown index for periodic sideb DOFs.
  • Returns the DOF's own unknown index for free/side_a DOFs.

Both dof_to_unknown and periodic_side_b_to_side_a_unknown are flat vectors indexed by global DOF, so this is a pure array lookup with no allocation — safe to call inside GPU kernels.

source
FiniteElementContainers.update_dofs!Method
update_dofs!(
    dof::DofManager,
    dirichlet_dofs::AbstractVector{<:Integer},
    periodic_side_a_dofs::AbstractVector{<:Integer},
    periodic_side_b_dofs::AbstractVector{<:Integer}
)

Takes in a list of dof ids associated with dirichlet bcs and updates the internals of dof to reflect these.

NOTE: This clears all existing bcs in dof and starts fresh.

source