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 Exodus, FiniteElementContainers
julia> mesh = UnstructuredMesh("../../test/poisson/poisson.g")
UnstructuredMesh{FileMesh{Exodus.ExodusDatabase{Int32, Int32, Int32, Float64}}, H1Field{Float64, Vector{Float64}, 2}, Vector{Symbol}, @NamedTuple{block_1::String}, @NamedTuple{block_1::L2ElementField{Int64, Vector{Int64}, 4}}, @NamedTuple{block_1::Vector{Int64}}, @NamedTuple{nset_1::Vector{Int64}, nset_2::Vector{Int64}, nset_3::Vector{Int64}, nset_4::Vector{Int64}}, @NamedTuple{sset_1::Vector{Int64}, sset_2::Vector{Int64}, sset_3::Vector{Int64}, sset_4::Vector{Int64}}, @NamedTuple{sset_1::Matrix{Int64}, sset_2::Matrix{Int64}, sset_3::Matrix{Int64}, sset_4::Matrix{Int64}}, Nothing, Nothing}(FileMesh{Exodus.ExodusDatabase{Int32, Int32, Int32, Float64}}("../../test/poisson/poisson.g", ExodusDatabase: File name = ../../test/poisson/poisson.g Mode = r Initialization: Number of dim = 2 Number of nodes = 16641 Number of elem = 16384 Number of blocks = 1 Number of node sets = 4 Number of side sets = 4 Block: block_1 NodeSet: nset_1 nset_2 nset_3 nset_4 SideSet: sset_1 sset_2 sset_3 sset_4 ElementVariable: GlobalVariable: NodalVariable: NodeSetVariable: SideSetVariable: ), [1.0 0.9921875 … 0.0078125 0.0; 1.0 1.0 … 0.0 0.0], [:block_1], (block_1 = "QUAD4",), (block_1 = [1 2 … 16510 16511; 2 5 … 16511 16512; 3 6 … 16640 16641; 4 3 … 16639 16640],), (block_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 … 16375, 16376, 16377, 16378, 16379, 16380, 16381, 16382, 16383, 16384],), (nset_1 = [1, 2, 5, 7, 9, 11, 13, 15, 17, 19 … 239, 241, 243, 245, 247, 249, 251, 253, 255, 257], nset_2 = [257, 258, 387, 516, 645, 774, 903, 1032, 1161, 1290 … 15480, 15609, 15738, 15867, 15996, 16125, 16254, 16383, 16512, 16641], nset_3 = [16513, 16514, 16515, 16516, 16517, 16518, 16519, 16520, 16521, 16522 … 16632, 16633, 16634, 16635, 16636, 16637, 16638, 16639, 16640, 16641], nset_4 = [1, 4, 260, 389, 518, 647, 776, 905, 1034, 1163 … 15353, 15482, 15611, 15740, 15869, 15998, 16127, 16256, 16385, 16514]), (sset_1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 … 119, 120, 121, 122, 123, 124, 125, 126, 127, 128], sset_2 = [128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280 … 15232, 15360, 15488, 15616, 15744, 15872, 16000, 16128, 16256, 16384], sset_3 = [16257, 16258, 16259, 16260, 16261, 16262, 16263, 16264, 16265, 16266 … 16375, 16376, 16377, 16378, 16379, 16380, 16381, 16382, 16383, 16384], sset_4 = [1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153 … 15105, 15233, 15361, 15489, 15617, 15745, 15873, 16001, 16129, 16257]), (sset_1 = [1, 2, 5, 7, 9, 11, 13, 15, 17, 19 … 239, 241, 243, 245, 247, 249, 251, 253, 255, 257], sset_2 = [257, 258, 387, 516, 645, 774, 903, 1032, 1161, 1290 … 15480, 15609, 15738, 15867, 15996, 16125, 16254, 16383, 16512, 16641], sset_3 = [16513, 16514, 16515, 16516, 16517, 16518, 16519, 16520, 16521, 16522 … 16632, 16633, 16634, 16635, 16636, 16637, 16638, 16639, 16640, 16641], sset_4 = [1, 4, 260, 389, 518, 647, 776, 905, 1034, 1163 … 15353, 15482, 15611, 15740, 15869, 15998, 16127, 16256, 16385, 16514]), (sset_1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], sset_2 = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2 … 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], sset_3 = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3 … 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], sset_4 = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4 … 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]), (sset_1 = [1 2 … 255 257], sset_2 = [257 258 … 16512 16641], sset_3 = [16513 16514 … 16641 16640], sset_4 = [4 1 … 16514 16385]), nothing, nothing)
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
Now we can supply these variables to the DofManager
which takes varargs as inputs
julia> dof = DofManager(u, t)
ERROR: MethodError: no method matching DofManager(::VectorFunction{(:u_x, :u_y), FunctionSpace{H1Field{Float64, Vector{Float64}, 2}, @NamedTuple{block_1::L2ElementField{Int64, Vector{Int64}, 4}}, @NamedTuple{block_1::ReferenceFiniteElements.ReferenceFE{ReferenceFiniteElements.Quad4{Lagrange, 2}, Vector{StaticArraysCore.SVector{2, Int64}}, Vector{StaticArraysCore.SVector{0, Union{}}}, Vector{Int64}, Vector{StaticArraysCore.SVector{2, Float64}}, Vector{ReferenceFiniteElements.SInterpolants{Float64, 2, 4, 8, 16}}, Matrix{StaticArraysCore.SVector{2, Float64}}, Matrix{ReferenceFiniteElements.SInterpolants{Float64, 2, 4, 8, 16}}}}}}, ::ScalarFunction{:t, FunctionSpace{H1Field{Float64, Vector{Float64}, 2}, @NamedTuple{block_1::L2ElementField{Int64, Vector{Int64}, 4}}, @NamedTuple{block_1::ReferenceFiniteElements.ReferenceFE{ReferenceFiniteElements.Quad4{Lagrange, 2}, Vector{StaticArraysCore.SVector{2, Int64}}, Vector{StaticArraysCore.SVector{0, Union{}}}, Vector{Int64}, Vector{StaticArraysCore.SVector{2, Float64}}, Vector{ReferenceFiniteElements.SInterpolants{Float64, 2, 4, 8, 16}}, Matrix{StaticArraysCore.SVector{2, Float64}}, Matrix{ReferenceFiniteElements.SInterpolants{Float64, 2, 4, 8, 16}}}}}}) Closest candidates are: DofManager(::FiniteElementContainers.AbstractFunction; use_condensed) @ FiniteElementContainers ~/work/FiniteElementContainers.jl/FiniteElementContainers.jl/src/DofManagers.jl:20
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)
ERROR: UndefVarError: `dof` not defined
We can create fields of the right size from the DofManager
with the following methods
julia> field = create_field(dof, H1Field)
ERROR: UndefVarError: `dof` not defined
These methods take the backed 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