Skip to content

Commit

Permalink
add!(::ConstraintHandler, ::Dirichlet) for nonconcrete celltypes (#427)
Browse files Browse the repository at this point in the history
* Make add\!(::ConstraintHandler, ::Dirichlet) work for nonconcrete celltypes

* Copy dbc for add! of multiple fieldhandlers, silence warn for this case

Add new warning if there is no overlap, but the warning for only partial overlap is silenced

* Add test of add constraint method for mixeddofhandler

* Add Logging as test dependency

* Recreate Dirichlet instead of deepcopy
  • Loading branch information
KnutAM committed Jan 9, 2023
1 parent a57b1c6 commit 372ab4a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"

[targets]
test = ["BlockArrays", "Downloads", "FerriteGmsh", "ForwardDiff", "Gmsh", "IterativeSolvers", "Metis", "NBInclude", "ProgressMeter", "Random", "SHA", "StableRNGs", "Test", "TimerOutputs"]
test = ["BlockArrays", "Downloads", "FerriteGmsh", "ForwardDiff", "Gmsh", "IterativeSolvers", "Metis", "NBInclude", "ProgressMeter", "Random", "SHA", "StableRNGs", "Test", "TimerOutputs", "Logging"]
31 changes: 29 additions & 2 deletions src/Dofs/ConstraintHandler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,35 @@ end


#Function for adding constraint when using multiple celltypes
function add!(ch::ConstraintHandler, fh::FieldHandler, dbc::Dirichlet)
_check_cellset_dirichlet(ch.dh.grid, fh.cellset, dbc.faces)
function add!(ch::ConstraintHandler{<:MixedDofHandler}, dbc::Dirichlet)
dbc_added = false
for fh in ch.dh.fieldhandlers
if overlaps(fh, dbc)
# Recreating the `dbc` will create a copy of `dbc.faces`.
# If `dbc` have dofs not in `fh`, these will be removed from `dbc`,
# thus the need to copy `dbc.faces`.
# In this case, add! will warn, unless warn_check_cellset=false
dbc_ = Dirichlet(dbc.field_name, dbc.faces, dbc.f,
isempty(dbc.components) ? nothing : dbc.components)
# Check for empty already done when user created `dbc`
add!(ch, fh, dbc_, warn_check_cellset=false)
dbc_added = true
end
end
dbc_added || @warn("No overlap between dbc::Dirichlet and fields in the ConstraintHandler's MixedDofHandler")
return ch
end

function overlaps(fh::FieldHandler, dbc::Dirichlet)
dbc.field_name in getfieldnames(fh) || return false # Must contain the correct field
for (cellid, _) in dbc.faces
cellid in fh.cellset && return true
end
return false
end

function add!(ch::ConstraintHandler, fh::FieldHandler, dbc::Dirichlet; warn_check_cellset=true)
warn_check_cellset && _check_cellset_dirichlet(ch.dh.grid, fh.cellset, dbc.faces)

celltype = getcelltype(ch.dh.grid, first(fh.cellset)) #Assume same celltype of all cells in fh.cellset

Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Ferrite
using Tensors
using Test
using Logging
using ForwardDiff
import SHA
using Random
Expand Down
71 changes: 71 additions & 0 deletions test/test_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,77 @@ end
@test ch.prescribed_dofs == [10, 11, 14, 25, 27]
end

@testset "edge bc mixed grid" begin
# Test mesh
# 6---7---8---9---10
# | |2 /| | | :u 1:5
# | 1 | / | 4 | 5 | :v 1:2
# | |/ 3| | |
# 1---2---3---4---5
#
# |---A---|---B---|
# |---C---|
#
# Dofs per node (note, depends on push! order below) (:u, [:v])
# node nr 1 2 3 4 5 6 7 8 9 10
nodedofs = [(1, 5), (2, 6), (11,), (12,), (14,), (4,8), (3,7), (9,10), (13,), (15,)]

# Create Grid based on above drawing
nodes = [Node{2,Float64}(Vec{2,Float64}((i, j))) for j in 0:1 for i in 0:4]
quadcells = [Quadrilateral((i, i+1, i+6, i+5)) for i in [1, 3, 4]]
tricells = [Triangle((2,8,7)), Triangle((2,3,8))]
cells = [quadcells[1], tricells..., quadcells[2:end]...]
cellsets = Dict("onlyuQ" => Set(4:5), "onlyuT" => Set(3:3),
"uandvQ" => Set(1:1), "uandvT" => Set(2:2))
facesets = Dict("A" => Set((FaceIndex(1,1), FaceIndex(3,1))),
"B" => Set((FaceIndex(4,1), FaceIndex(5,1))),
"C" => Set((FaceIndex(3,1), FaceIndex(4,1))))
grid = Grid(cells, nodes, cellsets=cellsets, facesets=facesets)

# Create MixedDofHandler based on grid
dim = Ferrite.getdim(grid) # 2
ip_quad = Lagrange{dim,RefCube,1}()
ip_tria = Lagrange{dim,RefTetrahedron,1}()
dh = MixedDofHandler(grid)
field_uT = Field(:u, ip_tria, 1)
field_uQ = Field(:u, ip_quad, 1)
field_vT = Field(:v, ip_tria, 1)
field_vQ = Field(:v, ip_quad, 1)

# Order important for test to ensure consistent dof ordering
push!(dh, FieldHandler([field_uQ, field_vQ], getcellset(grid, "uandvQ")))
push!(dh, FieldHandler([field_uT, field_vT], getcellset(grid, "uandvT")))
push!(dh, FieldHandler([field_uT], getcellset(grid, "onlyuT")))
push!(dh, FieldHandler([field_uQ], getcellset(grid, "onlyuQ")))
close!(dh)

# Add constraints
ch = ConstraintHandler(dh)
dA_u = Dirichlet(:u, getfaceset(grid, "A"), (x,t) -> 1.0)
dA_v = Dirichlet(:v, getfaceset(grid, "A"), (x,t) -> 2.0)
dB_u = Dirichlet(:u, getfaceset(grid, "B"), (x,t) -> 3.0) # Note, overwrites dA_u on node 3
dB_v = Dirichlet(:v, getfaceset(grid, "B"), (x,t) -> 4.0) # :v not on cells with "B"-faces
dC_v = Dirichlet(:v, getfaceset(grid, "C"), (x,t) -> 5.0) # :v not on cells with "C"-faces

@test_logs min_level=Logging.Warn add!(ch, dA_u) # No warning should be issued
@test_logs min_level=Logging.Warn add!(ch, dA_v) # No warning should be issued
@test_logs min_level=Logging.Warn add!(ch, dB_u) # No warning should be issued
@test_logs (:warn,) add!(ch, dB_v) # Warn about :v not in cells connected with dB_v's faceset
@test_logs (:warn,) add!(ch, dC_v) # Warn about :v not in cells connected with dC_v's faceset
close!(ch)

# The full bottom part of the mesh has been prescribed
@test sort(ch.prescribed_dofs) == sort([nd[i] for nd in nodedofs[1:5] for i in 1:length(nd)])

# Test that the correct dofs have been prescribed
update!(ch, 0.0)
# nodes N1, N2, N1, N2, N3, N4, N5
# field :u, :u, :v, :v, :u, :u, :u
# dof 1, 2, 5, 6, 11, 12, 14
@test ch.inhomogeneities == [1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 3.0]
# Note that dB_u overwrite dA_u @ N3, hence the value 3.0 there
end

@testset "affine constraints" begin

grid = generate_grid(Line, (10,))
Expand Down

0 comments on commit 372ab4a

Please sign in to comment.