Skip to content

Commit

Permalink
Implement support for Wedge/Triangular prism elements with correspond…
Browse files Browse the repository at this point in the history
…ing linear and quadratic interpolation (#581)
  • Loading branch information
termi-official authored Mar 17, 2023
1 parent 200b47a commit 1c01761
Show file tree
Hide file tree
Showing 19 changed files with 1,102 additions and 336 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Support for classical trilinear and triquadratic wedge elements. ([#581][github-581])
- Symmetric quadrature rules up to order 10 for prismatic elements. ([#581][github-581])
- Finer granulation of dof distribution, allowing to distribute different amounts of dofs
per entity. ([#581][github-581])
### Fixed
- Dof distribution for embedded elements. ([#581][github-581])
### Other improvements
- To clarify the dof management `vertices(ip)`, `edges(ip)` and `faces(ip)` has been
deprecated in favor of `vertexdof_indices(ip)`, `edgedof_indices(ip)` and
`facedof_indices(ip)`. ([#578][github-578])

## [0.3.12] - 2023-02-28
### Added
Expand Down Expand Up @@ -324,6 +335,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[github-574]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/574
[github-575]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/575
[github-578]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/578
[github-581]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/581
[github-583]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/583
[github-588]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/588
[github-591]: https://github.com/Ferrite-FEM/Ferrite.jl/pull/591
Expand Down
22 changes: 15 additions & 7 deletions docs/src/devdocs/interpolations.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,27 @@ Ferrite.getrefshape(::Interpolation)
Ferrite.getorder(::Interpolation)
Ferrite.value(::Interpolation{dim}, ::Vec{dim,T}) where {dim,T}
Ferrite.derivative(::Interpolation{dim}, ::Vec{dim}) where {dim}
Ferrite.boundarydof_indices
```

### Required methods to implement for all subtypes of `Interpolation` to define a new finite element

Depending on the dimension of the reference element the following functions have to be implemented

```@docs
Ferrite.value(::Interpolation, ::Int, ::Vec)
Ferrite.vertices(::Interpolation)
Ferrite.nvertexdofs(::Interpolation)
Ferrite.faces(::Interpolation)
Ferrite.nfacedofs(::Interpolation)
Ferrite.edges(::Interpolation)
Ferrite.nedgedofs(::Interpolation)
Ferrite.ncelldofs(::Interpolation)
Ferrite.vertexdof_indices(::Interpolation)
Ferrite.facedof_indices(::Interpolation)
Ferrite.facedof_interior_indices(::Interpolation)
Ferrite.edgedof_indices(::Interpolation)
Ferrite.edgedof_interior_indices(::Interpolation)
Ferrite.celldof_interior_indices(::Interpolation)
Ferrite.getnbasefunctions(::Interpolation)
Ferrite.reference_coordinates(::Interpolation)
```

for all entities which exist on that reference element. The dof functions default to having no
dofs defined on a specific entity. Hence, not overloading of the dof functions will result in an
element with zero dofs. Also, it should always be double checked that everything is consistent as
specified in the docstring of the corresponding function, as inconsistent implementations can
lead to bugs which are really difficult to track down.
27 changes: 13 additions & 14 deletions src/Dofs/ConstraintHandler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ end

function _add!(ch::ConstraintHandler, dbc::Dirichlet, bcfaces::Set{Index}, interpolation::Interpolation, field_dim::Int, offset::Int, bcvalue::BCValues, cellset::Set{Int}=Set{Int}(1:getncells(ch.dh.grid))) where {Index<:BoundaryIndex}
local_face_dofs, local_face_dofs_offset =
_local_face_dofs_for_bc(interpolation, field_dim, dbc.components, offset, boundaryfunction(eltype(bcfaces)))
_local_face_dofs_for_bc(interpolation, field_dim, dbc.components, offset, boundarydof_indices(eltype(bcfaces)))
copy!(dbc.local_face_dofs, local_face_dofs)
copy!(dbc.local_face_dofs_offset, local_face_dofs_offset)

Expand Down Expand Up @@ -337,7 +337,7 @@ end

# Calculate which local dof index live on each face:
# face `i` have dofs `local_face_dofs[local_face_dofs_offset[i]:local_face_dofs_offset[i+1]-1]
function _local_face_dofs_for_bc(interpolation, field_dim, components, offset, boundaryfunc::F=faces) where F
function _local_face_dofs_for_bc(interpolation, field_dim, components, offset, boundaryfunc::F=facedof_indices) where F
@assert issorted(components)
local_face_dofs = Int[]
local_face_dofs_offset = Int[1]
Expand Down Expand Up @@ -442,24 +442,23 @@ function update!(ch::ConstraintHandler, time::Real=0.0)
return nothing
end

# for faces
function _update!(inhomogeneities::Vector{Float64}, f::Function, faces::Set{<:BoundaryIndex}, field::Symbol, local_face_dofs::Vector{Int}, local_face_dofs_offset::Vector{Int},
components::Vector{Int}, dh::AbstractDofHandler, facevalues::BCValues,
# for vertices, faces and edges
function _update!(inhomogeneities::Vector{Float64}, f::Function, boundary_entities::Set{<:BoundaryIndex}, field::Symbol, local_face_dofs::Vector{Int}, local_face_dofs_offset::Vector{Int},
components::Vector{Int}, dh::AbstractDofHandler, boundaryvalues::BCValues,
dofmapping::Dict{Int,Int}, dofcoefficients::Vector{Union{Nothing,DofCoefficients{T}}}, time::Real) where {T}

cc = CellCache(dh, UpdateFlags(; nodes=false, coords=true, dofs=true))
for (cellidx, faceidx) in faces
for (cellidx, entityidx) in boundary_entities
reinit!(cc, cellidx)

# no need to reinit!, enough to update current_face since we only need geometric shape functions M
facevalues.current_face[] = faceidx
# no need to reinit!, enough to update current_entity since we only need geometric shape functions M
boundaryvalues.current_entity[] = entityidx

# local dof-range for this face
r = local_face_dofs_offset[faceidx]:(local_face_dofs_offset[faceidx+1]-1)
r = local_face_dofs_offset[entityidx]:(local_face_dofs_offset[entityidx+1]-1)
counter = 1

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

Expand Down Expand Up @@ -1302,7 +1301,7 @@ end
function mirror_local_dofs(local_face_dofs, local_face_dofs_offset, ip::Lagrange{2,<:Union{RefCube,RefTetrahedron}}, n::Int)
# For 2D we always permute since Ferrite defines dofs counter-clockwise
ret = collect(1:length(local_face_dofs))
for (i, f) in enumerate(faces(ip))
for (i, f) in enumerate(facedof_indices(ip))
this_offset = local_face_dofs_offset[i]
other_offset = this_offset + n
for d in 1:n
Expand All @@ -1323,7 +1322,7 @@ function mirror_local_dofs(local_face_dofs, local_face_dofs_offset, ip::Lagrange
ret = collect(1:length(local_face_dofs))

# Mirror by changing from counter-clockwise to clockwise
for (i, f) in enumerate(faces(ip))
for (i, f) in enumerate(facedof_indices(ip))
r = local_face_dofs_offset[i]:(local_face_dofs_offset[i+1] - 1)
# 1. Rotate the corners
vertex_range = r[1:(N*n)]
Expand Down
Loading

0 comments on commit 1c01761

Please sign in to comment.