Skip to content

Commit

Permalink
Rework CellIterator by extracting out the caching part
Browse files Browse the repository at this point in the history
This patch reworks the CellIterator by extracting out the caching parts
to its own CellCache struct that can be used independently. Elements of
a CellIterator are now CellCache instead of the CellIterator itself.
  • Loading branch information
fredrikekre committed Dec 19, 2022
1 parent fcda121 commit b8b6dcf
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 146 deletions.
1 change: 1 addition & 0 deletions docs/src/reference/dofhandler.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ Ferrite.getfielddim(::MixedDofHandler, ::Symbol)

# CellIterator
```@docs
CellCache
CellIterator
```
31 changes: 11 additions & 20 deletions src/Dofs/ConstraintHandler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,16 +306,16 @@ function _add!(ch::ConstraintHandler, dbc::Dirichlet, bcfaces::Set{Index}, inter

# loop over all the faces in the set and add the global dofs to `constrained_dofs`
constrained_dofs = Int[]
cc = CellCache(ch.dh, UpdateFlags(; nodes=false, coords=false, dofs=true))
for (cellidx, faceidx) in bcfaces
if cellidx cellset
delete!(dbc.faces, Index(cellidx, faceidx))
continue # skip faces that are not part of the cellset
end
_celldofs = fill(0, ndofs_per_cell(ch.dh, cellidx))
celldofs!(_celldofs, ch.dh, cellidx) # extract the dofs for this cell
reinit!(cc, cellidx)
r = local_face_dofs_offset[faceidx]:(local_face_dofs_offset[faceidx+1]-1)
append!(constrained_dofs, _celldofs[local_face_dofs[r]]) # TODO: for-loop over r and simply push! to ch.prescribed_dofs
@debug println("adding dofs $(_celldofs[local_face_dofs[r]]) to dbc")
append!(constrained_dofs, cc.dofs[local_face_dofs[r]]) # TODO: for-loop over r and simply push! to ch.prescribed_dofs
@debug println("adding dofs $(cc.dofs[local_face_dofs[r]]) to dbc")
end

# save it to the ConstraintHandler
Expand Down Expand Up @@ -352,18 +352,16 @@ function _add!(ch::ConstraintHandler, dbc::Dirichlet, bcnodes::Set{Int}, interpo
ncomps = length(dbc.components)
nnodes = getnnodes(ch.dh.grid)
interpol_points = getnbasefunctions(interpolation)
_celldofs = fill(0, ndofs_per_cell(ch.dh, first(cellset)))
node_dofs = zeros(Int, ncomps, nnodes)
visited = falses(nnodes)
for cell in CellIterator(ch.dh, collect(cellset)) # only go over cells that belong to current FieldHandler
celldofs!(_celldofs, cell) # update the dofs for this cell
for cell in CellIterator(ch.dh, cellset) # only go over cells that belong to current FieldHandler
for idx in 1:min(interpol_points, length(cell.nodes))
node = cell.nodes[idx]
if !visited[node]
noderange = (offset + (idx-1)*field_dim + 1):(offset + idx*field_dim) # the dofs in this node
for (i,c) in enumerate(dbc.components)
node_dofs[i,node] = _celldofs[noderange[c]]
@debug println("adding dof $(_celldofs[noderange[c]]) to node_dofs")
node_dofs[i,node] = cell.dofs[noderange[c]]
@debug println("adding dof $(cell.dofs[noderange[c]]) to node_dofs")
end
visited[node] = true
end
Expand Down Expand Up @@ -429,16 +427,9 @@ function _update!(inhomogeneities::Vector{Float64}, f::Function, faces::Set{<:Bo
components::Vector{Int}, dh::AbstractDofHandler, facevalues::BCValues,
dofmapping::Dict{Int,Int}, dofcoefficients::Vector{Union{Nothing,DofCoefficients{T}}}, time::T) where {T}

dim = getdim(dh.grid)
_tmp_cellid = first(faces)[1]

N = nnodes_per_cell(dh.grid, _tmp_cellid)
xh = zeros(Vec{dim, T}, N) # pre-allocate
_celldofs = fill(0, ndofs_per_cell(dh, _tmp_cellid))

cc = CellCache(dh, UpdateFlags(; nodes=false, coords=true, dofs=true))
for (cellidx, faceidx) in faces
cellcoords!(xh, dh, cellidx)
celldofs!(_celldofs, dh, cellidx) # update global dofs for this cell
reinit!(cc, cellidx)

# no need to reinit!, enough to update current_face since we only need geometric shape functions M
facevalues.current_face[] = faceidx
Expand All @@ -448,13 +439,13 @@ function _update!(inhomogeneities::Vector{Float64}, f::Function, faces::Set{<:Bo
counter = 1

for location in 1:getnquadpoints(facevalues)
x = spatial_coordinate(facevalues, location, xh)
x = spatial_coordinate(facevalues, location, cc.coords)
bc_value = f(x, time)
@assert length(bc_value) == length(components)

for i in 1:length(components)
# find the global dof
globaldof = _celldofs[local_face_dofs[r[counter]]]
globaldof = cc.dofs[local_face_dofs[r[counter]]]
counter += 1

dbc_index = dofmapping[globaldof]
Expand Down
7 changes: 3 additions & 4 deletions src/Dofs/DofHandler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,10 @@ function reshape_to_nodes(dh::DofHandler, u::Vector{T}, fieldname::Symbol) where
return data
end

function reshape_field_data!(data::Matrix{T}, dh::AbstractDofHandler, u::Vector{T}, field_offset::Int, field_dim::Int, cellset=Set{Int}(1:getncells(dh.grid))) where T
function reshape_field_data!(data::Matrix{T}, dh::AbstractDofHandler, u::Vector{T}, field_offset::Int, field_dim::Int, cellset=1:getncells(dh.grid)) where T

_celldofs = Vector{Int}(undef, ndofs_per_cell(dh, first(cellset)))
for cell in CellIterator(dh, collect(cellset))
celldofs!( _celldofs, cell)
for cell in CellIterator(dh, cellset, UpdateFlags(; nodes=true, coords=false, dofs=true))
_celldofs = celldofs(cell)
counter = 1
for node in getnodes(cell)
for d in 1:field_dim
Expand Down
4 changes: 2 additions & 2 deletions src/Dofs/DofRenumbering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ function compute_renumber_permutation(dh::DofHandler, _, order::DofOrder.Compone
dofs_for_blocks = [Set{Int}() for _ in 1:nblocks]
dof_ranges = [dof_range(dh, f) for f in dh.field_names]
component_offsets = pushfirst!(cumsum(dh.field_dims), 0)
flags = UpdateFlags(nodes=false, coords=false, celldofs=true)
@inbounds for cell in CellIterator(dh, #=cellset=# nothing, flags)
flags = UpdateFlags(nodes=false, coords=false, dofs=true)
@inbounds for cell in CellIterator(dh, flags)
cdofs = celldofs(cell)
for i in eachindex(dh.field_names)
rng = dof_ranges[i]
Expand Down
4 changes: 3 additions & 1 deletion src/FEValues/common_values.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ end
@noinline function throw_incompatible_coord_length(length_x, n_base_funcs)
throw(ArgumentError(
"the number of (geometric) base functions ($(n_base_funcs)) does not match " *
"the number of coordinates in the vector ($(length_x))."
"the number of coordinates in the vector ($(length_x)). Perhaps you forgot to " *
"use an appropriate geometric interpolation when creating FE values? See " *
"https://github.com/Ferrite-FEM/Ferrite.jl/issues/265 for more details."
))
end

Expand Down
3 changes: 1 addition & 2 deletions src/L2_projection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,9 @@ function reshape_to_nodes(proj::L2Projector, vals::AbstractVector{S}) where {ord
@assert ndofs(dh) == length(vals)
nout = S <: Vec{2} ? 3 : M # Pad 2D Vec to 3D
data = fill(T(NaN), nout, getnnodes(dh.grid))
_celldofs = Vector{Int}(undef, ndofs_per_cell(dh, first(proj.set)))
for cell in CellIterator(dh, proj.set)
_celldofs = celldofs(cell)
@assert length(getnodes(cell)) == length(_celldofs)
celldofs!(_celldofs, cell)
for (node, dof) in zip(getnodes(cell), _celldofs)
v = @view data[:, node]
fill!(v, 0) # remove NaNs for this node
Expand Down
1 change: 1 addition & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export
ApplyStrategy,

# iterators
CellCache,
CellIterator,
UpdateFlags,
cellid,
Expand Down
Loading

0 comments on commit b8b6dcf

Please sign in to comment.