From e7bb02e3dd667739da890bdee2985ab3a80fbf11 Mon Sep 17 00:00:00 2001 From: termi-official Date: Fri, 1 Mar 2024 19:51:33 +0100 Subject: [PATCH 01/13] Update some missing Lagrange docs. --- docs/src/topics/degrees_of_freedom.md | 8 ++++---- docs/src/topics/grid.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/src/topics/degrees_of_freedom.md b/docs/src/topics/degrees_of_freedom.md index 151834cb09..90825d13ec 100644 --- a/docs/src/topics/degrees_of_freedom.md +++ b/docs/src/topics/degrees_of_freedom.md @@ -25,8 +25,8 @@ need to specify number of components for the field. Here we add a vector field ` (2 components for a 2D problem) and a scalar field `:p`. ```@example dofs -add!(dh, :u, Lagrange{2,RefTetrahedron,1}()^2) -add!(dh, :p, Lagrange{2,RefTetrahedron,1}()) +add!(dh, :u, Lagrange{RefTriangle,1}()^2) +add!(dh, :p, Lagrange{RefTriangle,1}()) # hide ``` @@ -53,8 +53,8 @@ quadratic interpolation, and our `:p` field with a linear approximation. ```@example dofs dh = DofHandler(grid) # hide -add!(dh, :u, Lagrange{2,RefTetrahedron,2}()^2) -add!(dh, :p, Lagrange{2,RefTetrahedron,1}()) +add!(dh, :u, Lagrange{RefTriangle,2}()^2) +add!(dh, :p, Lagrange{RefTriangle,1}()) # hide ``` diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index c232d55eec..9acf9d709e 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -86,7 +86,7 @@ In this space a local numbering of nodes and faces exists, i.e. The example shows a local face ID ordering, defined as: ```julia -faces(::Lagrange{2,RefCube,1}) = ((1,2), (2,3), (3,4), (4,1)) +faces(::Lagrange{RefQuadrilateral,1}) = ((1,2), (2,3), (3,4), (4,1)) ``` Other face ID definitions [can be found in the src files](https://github.com/Ferrite-FEM/Ferrite.jl/blob/8224282ab4d67cb523ef342e4a6ceb1716764ada/src/interpolations.jl#L154) in the corresponding `faces` dispatch. @@ -123,7 +123,7 @@ julia> function compute_faceset(cells, global_faces, ip::Interpolation{dim}) whe return faces end -julia> interpolation = Lagrange{2, RefCube, 1}() +julia> interpolation = Lagrange{RefQuadrilateral, 1}() julia> compute_faceset(cells, faces, interpolation) Vector{FaceIndex} with 2 elements: From b19fad76d9d54ddcbcebb91d7de4b370e7d055f4 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 4 Mar 2024 02:59:57 +0100 Subject: [PATCH 02/13] Apply suggestions from code review Co-authored-by: Knut Andreas Meyer --- docs/src/topics/degrees_of_freedom.md | 8 ++++---- docs/src/topics/grid.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/src/topics/degrees_of_freedom.md b/docs/src/topics/degrees_of_freedom.md index 90825d13ec..42cc4d47e8 100644 --- a/docs/src/topics/degrees_of_freedom.md +++ b/docs/src/topics/degrees_of_freedom.md @@ -25,8 +25,8 @@ need to specify number of components for the field. Here we add a vector field ` (2 components for a 2D problem) and a scalar field `:p`. ```@example dofs -add!(dh, :u, Lagrange{RefTriangle,1}()^2) -add!(dh, :p, Lagrange{RefTriangle,1}()) +add!(dh, :u, Lagrange{RefTriangle, 1}()^2) +add!(dh, :p, Lagrange{RefTriangle, 1}()) # hide ``` @@ -53,8 +53,8 @@ quadratic interpolation, and our `:p` field with a linear approximation. ```@example dofs dh = DofHandler(grid) # hide -add!(dh, :u, Lagrange{RefTriangle,2}()^2) -add!(dh, :p, Lagrange{RefTriangle,1}()) +add!(dh, :u, Lagrange{RefTriangle, 2}()^2) +add!(dh, :p, Lagrange{RefTriangle, 1}()) # hide ``` diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index 9acf9d709e..d220d471c8 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -86,7 +86,7 @@ In this space a local numbering of nodes and faces exists, i.e. The example shows a local face ID ordering, defined as: ```julia -faces(::Lagrange{RefQuadrilateral,1}) = ((1,2), (2,3), (3,4), (4,1)) +Ferrite.faces(::Lagrange{RefQuadrilateral, 1}) = ((1,2), (2,3), (3,4), (4,1)) ``` Other face ID definitions [can be found in the src files](https://github.com/Ferrite-FEM/Ferrite.jl/blob/8224282ab4d67cb523ef342e4a6ceb1716764ada/src/interpolations.jl#L154) in the corresponding `faces` dispatch. From 5622856ffc4ccb067a406c6b3bf3881da0dca2b6 Mon Sep 17 00:00:00 2001 From: termi-official Date: Mon, 3 Jun 2024 15:48:18 +0200 Subject: [PATCH 03/13] Change something. Broke everything. --- docs/src/topics/degrees_of_freedom.md | 2 +- docs/src/topics/grid.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/src/topics/degrees_of_freedom.md b/docs/src/topics/degrees_of_freedom.md index 42cc4d47e8..e044eea9d3 100644 --- a/docs/src/topics/degrees_of_freedom.md +++ b/docs/src/topics/degrees_of_freedom.md @@ -61,4 +61,4 @@ add!(dh, :p, Lagrange{RefTriangle, 1}()) ## Ordering of Dofs ordered in the same order as we add to dofhandler -nodes -> (edges ->) faces -> cells +vertices -> edges -> faces -> volumes diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index fc1bb559eb..2a3dc217b0 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -18,7 +18,7 @@ Either, a mesh is created on the fly with the gmsh API or a mesh in `.msh` or `. ```@docs FerriteGmsh.togrid ``` -`FerriteGmsh.jl` supports currently the translation of `cellsets` and `facesets`. +`FerriteGmsh.jl` supports currently the translation of `cellsets` and `facetsets`. Such sets are defined in Gmsh as `PhysicalGroups` of dimension `dim` and `dim-1`, respectively. In case only a part of the mesh is the domain, the domain can be specified by providing the keyword argument `domain` the name of the `PhysicalGroups` in the [`FerriteGmsh.togrid`](@ref) function. @@ -71,28 +71,28 @@ julia> cells = [ ``` where each Quadrilateral, which is a subtype of `AbstractCell` saves in the field `nodes` the tuple of node IDs. -Additionally, the data structure `Grid` can hold node-, face- and cellsets. +Additionally, the data structure `Grid` can hold node-, facet- and cellsets. All of these three sets are defined by a dictionary that maps a string key to a `Set`. For the special case of node- and cellsets the dictionary's value is of type `Set{Int}`, i.e. a keyword is mapped to a node or cell ID, respectively. -Facesets are a more elaborate construction. They map a `String` key to a `Set{FaceIndex}`, where each `FaceIndex` consists of `(global_cell_id, local_face_id)`. -In order to understand the `local_face_id` properly, one has to consider the reference space of the element, which typically is spanned by a product of the interval ``[-1, 1]`` and in this particular example ``[-1, 1] \times [-1, 1]``. -In this space a local numbering of nodes and faces exists, i.e. +Facesets are a more elaborate construction. They map a `String` key to a `Set{FaceIndex}`, where each `FaceIndex` consists of `(global_cell_id, local_facet_id)`. +In order to understand the `local_facet_id` properly, one has to consider the reference space of the element, which typically is spanned by a product of the interval ``[-1, 1]`` and in this particular example ``[-1, 1] \times [-1, 1]``. +In this space a local numbering of nodes and facets exists, i.e. ![local element](./assets/local_element.svg) -The example shows a local face ID ordering, defined as: +The example shows a local edge ordering, defined as: ```julia -Ferrite.faces(::Lagrange{RefQuadrilateral, 1}) = ((1,2), (2,3), (3,4), (4,1)) +Ferrite.reference_facets(RefQuadrilateral) = ((1,2), (2,3), (3,4), (4,1)) ``` -Other face ID definitions [can be found in the src files](https://github.com/Ferrite-FEM/Ferrite.jl/blob/8224282ab4d67cb523ef342e4a6ceb1716764ada/src/interpolations.jl#L154) in the corresponding `faces` dispatch. +Other facet definitions can be found in the src file `src/Grid/grid.jl` in the corresponding dispatches for [`reference_facets`](@ref Ferrite.reference_facets). Furthermorem you can query specific information about subentities via [`reference_vertices`](@ref Ferrite.reference_vertices), [`reference_edges`](@ref Ferrite.reference_edges) and [`reference_faces`](@ref Ferrite.reference_faces). -The highlighted face, i.e. the two lines from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as +The highlighted edge, i.e. the two lines from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as ```julia julia> faces = [ From ac5f104e0cee154f97c4a9f3afc58b4c0c436e55 Mon Sep 17 00:00:00 2001 From: termi-official Date: Mon, 3 Jun 2024 16:47:20 +0200 Subject: [PATCH 04/13] Add some missing docs and update the example in the topics. --- docs/src/devdocs/elements.md | 9 +++-- docs/src/topics/grid.md | 75 ++++++++++++++++++++++++------------ src/Grid/grid.jl | 31 +++++++++++++++ 3 files changed, 88 insertions(+), 27 deletions(-) diff --git a/docs/src/devdocs/elements.md b/docs/src/devdocs/elements.md index 265a2b13d4..18eb13a5a5 100644 --- a/docs/src/devdocs/elements.md +++ b/docs/src/devdocs/elements.md @@ -2,17 +2,20 @@ ## Type definitions -Elements or cells are subtypes of `AbstractCell{dim,N,M}`. They are parametrized by -the dimension of their nodes via `dim`, the number of nodes `N` and the number -of faces `M`. +Elements or cells are subtypes of `AbstractCell{<:AbstractRefShape}`. As shown, they are parametrized +by the associated reference element. ### Required methods to implement for all subtypes of `AbstractCell` to define a new element ```@docs +Ferrite.reference_vertices(::Ferrite.AbstractRefShape) Ferrite.vertices(::Ferrite.AbstractCell) +Ferrite.reference_edges(::Ferrite.AbstractRefShape) Ferrite.edges(::Ferrite.AbstractCell) Ferrite.reference_faces(::Ferrite.AbstractRefShape) Ferrite.faces(::Ferrite.AbstractCell) +Ferrite.reference_facets(::Ferrite.AbstractRefShape) +Ferrite.facets(::Ferrite.AbstractCell) Ferrite.geometric_interpolation(::Ferrite.AbstractCell) ``` diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index 2a3dc217b0..97c2eccbb7 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -92,46 +92,73 @@ Ferrite.reference_facets(RefQuadrilateral) = ((1,2), (2,3), (3,4), (4,1)) Other facet definitions can be found in the src file `src/Grid/grid.jl` in the corresponding dispatches for [`reference_facets`](@ref Ferrite.reference_facets). Furthermorem you can query specific information about subentities via [`reference_vertices`](@ref Ferrite.reference_vertices), [`reference_edges`](@ref Ferrite.reference_edges) and [`reference_faces`](@ref Ferrite.reference_faces). -The highlighted edge, i.e. the two lines from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as +The highlighted facet, i.e. the two lines from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as ```julia -julia> faces = [ +julia> facets = [ (3,6), (6,9) ] ``` -The local ID can be constructed based on elements, corresponding faces and chosen interpolation, since the face ordering is interpolation dependent. +Now to a full example. Let us reconstruct the local facets of a grid boundary with the decsribed machinery to see how everything +fits together: ```julia -julia> function compute_faceset(cells, global_faces, ip::Interpolation{dim}) where {dim} - local_faces = Ferrite.faces(ip) - nodes_per_face = length(local_faces[1]) - d = Dict{NTuple{nodes_per_face, Int}, FaceIndex}() +julia> function recompute_facetset_on_boundary(cells, global_facets) + # Facets in 2D are edges and have two vertices + d = Dict{NTuple{2, Int}, FacetIndex}() for (c, cell) in enumerate(cells) # c is global cell number - for (f, face) in enumerate(local_faces) # f is local face number - # store the global nodes for the particular element, local face combination - d[ntuple(i-> cell.nodes[face[i]], nodes_per_face)] = FaceIndex(c, f) + # Grab all local facets + local_facets = Ferrite.reference_facets(cell) + for (f, facet) in enumerate(local_facets) # f is local facet number + # Translate into global nodes + global_facet = ntuple(i-> cell.nodes[facet[i]], length(facet)) + d[global_facet] = FacetIndex(c, f) end end - faces = Vector{FaceIndex}() - for face in global_faces - # lookup the element, local face combination for this face - push!(faces, d[face]) + facets = Vector{FacetIndex}() + for facet in global_facets + # lookup the element, local facet combination for this facet + push!(facets, d[facet]) end - return faces + return facets end -julia> interpolation = Lagrange{RefQuadrilateral, 1}() - -julia> compute_faceset(cells, faces, interpolation) -Vector{FaceIndex} with 2 elements: - FaceIndex((2, 2)) - FaceIndex((4, 2)) +julia> recompute_facetset_on_boundary(cells, facets) +Vector{FacetIndex} with 2 elements: + FacetIndex((2, 2)) + FacetIndex((4, 2)) ``` -Ferrite considers edges only in the three dimensional space. However, they share the concepts of faces in terms of `(global_cell_id,local_edge_id)` identifier. +Note that this example can be simplified by directly using `Ferrite.facets`: + +```julia +julia> function recompute_facetset_on_boundary_alternative(cells, global_facets) + # Facets in 2D are edges and have two vertices + d = Dict{NTuple{2, Int}, FacetIndex}() + for (c, cell) in enumerate(cells) # c is global cell number + # Grab all local facets + for (f, global_facet) in enumerate(Ferrite.facets(cell)) # f is local facet number + d[global_facet] = FacetIndex(c, f) + end + end + + facets = Vector{FacetIndex}() + for facet in global_facets + # lookup the element, local facet combination for this facet + push!(facets, d[facet]) + end + + return facets + end + +julia> recompute_facetset_on_boundary_alternative(cells, facets) +Vector{FacetIndex} with 2 elements: + FacetIndex((2, 2)) + FacetIndex((4, 2)) +``` ## AbstractGrid @@ -182,6 +209,6 @@ In order to use boundaries, e.g. for Dirichlet constraints in the ConstraintHand ## Topology -Ferrite.jl's `Grid` type offers experimental features w.r.t. topology information. The functions [`Ferrite.getneighborhood`](@ref) and [`Ferrite.faceskeleton`](@ref) +Ferrite.jl's `Grid` type offers experimental features w.r.t. topology information. The functions [`Ferrite.getneighborhood`](@ref) and [`Ferrite.facetskeleton`](@ref) are the interface to obtain topological information. The [`Ferrite.getneighborhood`](@ref) can construct lists of directly connected entities based on a given entity (`CellIndex,FaceIndex,EdgeIndex,VertexIndex`). -The [`Ferrite.faceskeleton`](@ref) function can be used to evaluate integrals over material interfaces or computing element interface values such as jumps. +The [`Ferrite.facetskeleton`](@ref) function can be used to evaluate integrals over material interfaces or computing element interface values such as jumps. diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index a9fd0548e9..7016a11210 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -55,6 +55,16 @@ nedges( ::Type{T}) where {T <: AbstractRefShape} = length(reference_edges(T)) nfaces( ::Type{T}) where {T <: AbstractRefShape} = length(reference_faces(T)) nfacets( ::Type{T}) where {T <: AbstractRefShape} = length(reference_facets(T)) + +""" + reference_vertices(::AbstractRefShape) + reference_vertices(::AbstractCell) + +Returns a tuple of integers containing the ordered local vertex indices corresponding to +the corners or endpoints of an element. +""" +reference_vertices(::AbstractRefShape) + """ Ferrite.vertices(::AbstractCell) @@ -64,6 +74,20 @@ corresponds to the local index into this tuple. """ vertices(::AbstractCell) +""" + reference_edges(::AbstractRefShape) + reference_edges(::AbstractCell) + +Returns a tuple of 2-tuples containing the ordered local node indices corresponding to +the vertices that define an *oriented edge*. + +An *oriented edge* is an edge with the first node having the lowest local index and the other +node the secon dindex. + +Note that the vertices are sufficient to define a face uniquely. +""" +reference_edges(::AbstractRefShape) + """ Ferrite.edges(::AbstractCell) @@ -77,6 +101,7 @@ edges(::AbstractCell) """ reference_faces(::AbstractRefShape) + reference_faces(::AbstractCell) Returns a tuple of n-tuples containing the ordered local node indices corresponding to the vertices that define an *oriented face*. @@ -119,6 +144,7 @@ facets(::AbstractCell) """ Ferrite.reference_facets(::Type{<:AbstractRefShape}) + Ferrite.reference_facets(::AbstractCell) Returns a tuple of n-tuples containing the ordered local node indices corresponding to the vertices that define an oriented facet. @@ -131,6 +157,11 @@ reference_facets(::Type{<:AbstractRefShape}) @inline reference_facets(refshape::Type{<:AbstractRefShape{2}}) = reference_edges(refshape) @inline reference_facets(refshape::Type{<:AbstractRefShape{3}}) = reference_faces(refshape) +@inline reference_faces(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_faces(refshape) +@inline reference_edges(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_edges(refshape) +@inline reference_vertices(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_vertices(refshape) +@inline reference_facets(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_facets(refshape) + """ geometric_interpolation(::AbstractCell)::Interpolation From 1cd9a822264b421d87939d18b286da2be2c8293b Mon Sep 17 00:00:00 2001 From: termi-official Date: Mon, 3 Jun 2024 19:34:28 +0200 Subject: [PATCH 05/13] Apply Knuts suggestions. --- docs/src/devdocs/elements.md | 27 ++++++++++++++++++++------- docs/src/devdocs/reference_cells.md | 16 ++++++++++++++++ src/Grid/grid.jl | 17 +++++++++-------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/docs/src/devdocs/elements.md b/docs/src/devdocs/elements.md index 18eb13a5a5..7acca5de35 100644 --- a/docs/src/devdocs/elements.md +++ b/docs/src/devdocs/elements.md @@ -8,22 +8,35 @@ by the associated reference element. ### Required methods to implement for all subtypes of `AbstractCell` to define a new element ```@docs -Ferrite.reference_vertices(::Ferrite.AbstractRefShape) +Ferrite.get_node_ids +``` + +Please note that if your cell holds a single tuple called `nodes` to carry the node numbers, then +this method will work automatically. Almost all functions work automatically with the information +provided by the reference element. + +Please note that if you want to implement a custom element which does not have a reference shape, +then the relevant functions below need to be dispatched. + +### Common utilities and definitions when working with grids internally. + +First we have some topological queries on the element + +```@docs Ferrite.vertices(::Ferrite.AbstractCell) -Ferrite.reference_edges(::Ferrite.AbstractRefShape) Ferrite.edges(::Ferrite.AbstractCell) -Ferrite.reference_faces(::Ferrite.AbstractRefShape) Ferrite.faces(::Ferrite.AbstractCell) -Ferrite.reference_facets(::Ferrite.AbstractRefShape) Ferrite.facets(::Ferrite.AbstractCell) -Ferrite.geometric_interpolation(::Ferrite.AbstractCell) +Ferrite.boundaryfunction(::Type{<:Ferrite.BoundaryIndex}) +Ferrite.reference_vertices(::Ferrite.AbstractCell) +Ferrite.reference_edges(::Ferrite.AbstractCell) +Ferrite.reference_faces(::Ferrite.AbstractCell) ``` -### Common utilities and definitions when working with grids internally. +and some generic utils which are commonly found in finite element codes ```@docs Ferrite.BoundaryIndex -Ferrite.boundaryfunction(::Type{<:Ferrite.BoundaryIndex}) Ferrite.get_coordinate_eltype(::Ferrite.AbstractGrid) Ferrite.get_coordinate_eltype(::Node) Ferrite.toglobal diff --git a/docs/src/devdocs/reference_cells.md b/docs/src/devdocs/reference_cells.md index e48e99264c..7fe17541f1 100644 --- a/docs/src/devdocs/reference_cells.md +++ b/docs/src/devdocs/reference_cells.md @@ -15,3 +15,19 @@ Ferrite.RefTetrahedron Ferrite.RefHexahedron Ferrite.RefPrism ``` + +### Required methods to implement for all subtypes of `AbstractRefShape` to define a new reference element + +```@docs +Ferrite.geometric_interpolation(::Ferrite.AbstractRefShape) +Ferrite.reference_vertices(::Ferrite.AbstractRefShape) +Ferrite.reference_edges(::Ferrite.AbstractRefShape) +Ferrite.reference_faces(::Ferrite.AbstractRefShape) +``` + +which automatically defines + + +```@docs +Ferrite.reference_facets(::Ferrite.AbstractRefShape) +``` diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index 7016a11210..6a95d40aa5 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -63,7 +63,7 @@ nfacets( ::Type{T}) where {T <: AbstractRefShape} = length(reference_facets(T)) Returns a tuple of integers containing the ordered local vertex indices corresponding to the corners or endpoints of an element. """ -reference_vertices(::AbstractRefShape) +reference_vertices(::Union{AbstractRefShape, AbstractCell}) """ Ferrite.vertices(::AbstractCell) @@ -86,7 +86,7 @@ node the secon dindex. Note that the vertices are sufficient to define a face uniquely. """ -reference_edges(::AbstractRefShape) +reference_edges(::Union{AbstractRefShape, AbstractCell}) """ Ferrite.edges(::AbstractCell) @@ -111,7 +111,7 @@ nodes spanning such that the normal to the face is pointing outwards. Note that the vertices are sufficient to define a face uniquely. """ -reference_faces(::AbstractRefShape) +reference_faces(::Union{AbstractRefShape, AbstractCell}) """ Ferrite.faces(::AbstractCell) @@ -157,18 +157,19 @@ reference_facets(::Type{<:AbstractRefShape}) @inline reference_facets(refshape::Type{<:AbstractRefShape{2}}) = reference_edges(refshape) @inline reference_facets(refshape::Type{<:AbstractRefShape{3}}) = reference_faces(refshape) -@inline reference_faces(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_faces(refshape) -@inline reference_edges(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_edges(refshape) -@inline reference_vertices(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_vertices(refshape) -@inline reference_facets(::AbstractCell{refshape}) where refshape <:AbstractRefShape = reference_facets(refshape) +@inline reference_faces(::AbstractCell{refshape}) where refshape = reference_faces(refshape) +@inline reference_edges(::AbstractCell{refshape}) where refshape = reference_edges(refshape) +@inline reference_vertices(::AbstractCell{refshape}) where refshape = reference_vertices(refshape) +@inline reference_facets(::AbstractCell{refshape}) where refshape = reference_facets(refshape) """ geometric_interpolation(::AbstractCell)::Interpolation + geometric_interpolation(::Type{AbstractCell})::Interpolation Each `AbstractCell` type has a unique geometric interpolation describing its geometry. This function returns that interpolation. """ -geometric_interpolation(::AbstractCell) +geometric_interpolation(::T) where T <: AbstractCell = geometric_interpolation(T) """ Ferrite.get_node_ids(c::AbstractCell) From 978bea28cb8cd3fe444aabe4fe34a9f3e2610792 Mon Sep 17 00:00:00 2001 From: termi-official Date: Tue, 9 Jul 2024 21:43:47 +0200 Subject: [PATCH 06/13] Remove example to discuss separately --- docs/src/topics/grid.md | 59 ----------------------------------------- 1 file changed, 59 deletions(-) diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index 3c60b19d82..ef11e5eeb8 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -114,65 +114,6 @@ The unique representation of an entity is given by the sorted version of this tu While we could use this information to construct a facet set, Ferrite can construct this set by filtering based on the coordinates, using [`addfacetset!`](@ref). -Now to a full example. Let us reconstruct the local facets of a grid boundary with the described machinery to see how everything -fits together: -```julia -julia> function recompute_facetset_on_boundary(cells, global_facets) - # Facets in 2D are edges and have two vertices - d = Dict{NTuple{2, Int}, FacetIndex}() - for (c, cell) in enumerate(cells) # c is global cell number - # Grab all local facets - local_facets = Ferrite.reference_facets(cell) - for (f, facet) in enumerate(local_facets) # f is local facet number - # Translate into global nodes - global_facet = ntuple(i-> cell.nodes[facet[i]], length(facet)) - d[global_facet] = FacetIndex(c, f) - end - end - - facets = Vector{FacetIndex}() - for facet in global_facets - # lookup the element, local facet combination for this facet - push!(facets, d[facet]) - end - - return facets - end - -julia> recompute_facetset_on_boundary(cells, facets) -Vector{FacetIndex} with 2 elements: - FacetIndex((2, 2)) - FacetIndex((4, 2)) -``` - -Note that this example can be simplified by directly using `Ferrite.facets`: - -```julia -julia> function recompute_facetset_on_boundary_alternative(cells, global_facets) - # Facets in 2D are edges and have two vertices - d = Dict{NTuple{2, Int}, FacetIndex}() - for (c, cell) in enumerate(cells) # c is global cell number - # Grab all local facets - for (f, global_facet) in enumerate(Ferrite.facets(cell)) # f is local facet number - d[global_facet] = FacetIndex(c, f) - end - end - - facets = Vector{FacetIndex}() - for facet in global_facets - # lookup the element, local facet combination for this facet - push!(facets, d[facet]) - end - - return facets - end - -julia> recompute_facetset_on_boundary_alternative(cells, facets) -Vector{FacetIndex} with 2 elements: - FacetIndex((2, 2)) - FacetIndex((4, 2)) -``` - ## AbstractGrid It can be very useful to use a grid type for a certain special case, e.g. mixed cell types, adaptivity, IGA, etc. From 7f6349511f8fc1a9d6fe643a0b940f845d30926e Mon Sep 17 00:00:00 2001 From: Dennis Ogiermann Date: Wed, 10 Jul 2024 12:24:16 +0200 Subject: [PATCH 07/13] Apply suggestions from code review Co-authored-by: Knut Andreas Meyer --- docs/src/devdocs/reference_cells.md | 11 +++++------ src/Grid/grid.jl | 12 ++++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/src/devdocs/reference_cells.md b/docs/src/devdocs/reference_cells.md index 7fe17541f1..e75cf006a0 100644 --- a/docs/src/devdocs/reference_cells.md +++ b/docs/src/devdocs/reference_cells.md @@ -16,18 +16,17 @@ Ferrite.RefHexahedron Ferrite.RefPrism ``` -### Required methods to implement for all subtypes of `AbstractRefShape` to define a new reference element +### Required methods to implement for all subtypes of `AbstractRefShape` to define a new reference shape ```@docs -Ferrite.geometric_interpolation(::Ferrite.AbstractRefShape) -Ferrite.reference_vertices(::Ferrite.AbstractRefShape) -Ferrite.reference_edges(::Ferrite.AbstractRefShape) -Ferrite.reference_faces(::Ferrite.AbstractRefShape) +Ferrite.reference_vertices(::Type{<:Ferrite.AbstractRefShape}) +Ferrite.reference_edges(::Type{<:Ferrite.AbstractRefShape}) +Ferrite.reference_faces(::Type{<:Ferrite.AbstractRefShape}) ``` which automatically defines ```@docs -Ferrite.reference_facets(::Ferrite.AbstractRefShape) +Ferrite.reference_facets(::Type{<:Ferrite.AbstractRefShape}) ``` diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index 10a0511cef..92883e1eca 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -58,13 +58,13 @@ nfacets( ::Type{T}) where {T <: AbstractRefShape} = length(reference_facets(T)) """ - reference_vertices(::AbstractRefShape) + reference_vertices(::Type{<:AbstractRefShape}) reference_vertices(::AbstractCell) Returns a tuple of integers containing the ordered local vertex indices corresponding to the corners or endpoints of an element. """ -reference_vertices(::Union{AbstractRefShape, AbstractCell}) +reference_vertices(::Union{Type{<:AbstractRefShape}, AbstractCell}) """ Ferrite.vertices(::AbstractCell) @@ -76,7 +76,7 @@ corresponds to the local index into this tuple. vertices(::AbstractCell) """ - reference_edges(::AbstractRefShape) + reference_edges(::Type{<:AbstractRefShape}) reference_edges(::AbstractCell) Returns a tuple of 2-tuples containing the ordered local node indices corresponding to @@ -87,7 +87,7 @@ node the secon dindex. Note that the vertices are sufficient to define a face uniquely. """ -reference_edges(::Union{AbstractRefShape, AbstractCell}) +reference_edges(::Union{Type{<:AbstractRefShape}, AbstractCell}) """ Ferrite.edges(::AbstractCell) @@ -101,7 +101,7 @@ Note that the vertices are sufficient to define an edge uniquely. edges(::AbstractCell) """ - reference_faces(::AbstractRefShape) + reference_faces(::Type{<:AbstractRefShape}) reference_faces(::AbstractCell) Returns a tuple of n-tuples containing the ordered local node indices corresponding to @@ -112,7 +112,7 @@ nodes spanning such that the normal to the face is pointing outwards. Note that the vertices are sufficient to define a face uniquely. """ -reference_faces(::Union{AbstractRefShape, AbstractCell}) +reference_faces(::Union{Type{<:AbstractRefShape}, AbstractCell}) """ Ferrite.faces(::AbstractCell) From b90d6660a997a7d8607e76a2ef84038c5ca81ea9 Mon Sep 17 00:00:00 2001 From: Dennis Ogiermann Date: Wed, 10 Jul 2024 13:15:47 +0200 Subject: [PATCH 08/13] Apply suggestions from code review Co-authored-by: Knut Andreas Meyer --- docs/src/topics/grid.md | 16 ---------------- src/Grid/grid.jl | 4 ++-- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index ef11e5eeb8..4fa2e211bd 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -78,22 +78,6 @@ Facet- and vertexsets are represented by `OrderedSet{<:BoundaryIndex}`, where `B `FacetIndex` and `VertexIndex` wraps a `Tuple`, `(global_cell_id, local_facet_id)` and `(global_cell_id, local_vertex_id)`, where the local IDs are defined according to the reference shapes, see [Reference shapes](@ref). -Facetsets are a more elaborate construction. They map a `String` key to a `Set{FaceIndex}`, where each `FaceIndex` consists of `(global_cell_id, local_facet_id)`. -In order to understand the `local_facet_id` properly, one has to consider the reference space of the element, which typically is spanned by a product of the interval ``[-1, 1]`` and in this particular example ``[-1, 1] \times [-1, 1]``. -In this space a local numbering of nodes and facets exists, i.e. - -![local element](./assets/local_element.svg) - - -The example shows a local edge ordering, defined as: - -```julia -Ferrite.reference_facets(RefQuadrilateral) = ((1,2), (2,3), (3,4), (4,1)) -``` - -Other facet definitions can be found in the src file `src/Grid/grid.jl` in the corresponding dispatches for [`reference_facets`](@ref Ferrite.reference_facets). Furthermorem you can query specific information about subentities via [`reference_vertices`](@ref Ferrite.reference_vertices), [`reference_edges`](@ref Ferrite.reference_edges) and [`reference_faces`](@ref Ferrite.reference_faces). - - The highlighted facets, i.e. the two edges from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as ```julia diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index 92883e1eca..cead83c522 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -61,8 +61,8 @@ nfacets( ::Type{T}) where {T <: AbstractRefShape} = length(reference_facets(T)) reference_vertices(::Type{<:AbstractRefShape}) reference_vertices(::AbstractCell) -Returns a tuple of integers containing the ordered local vertex indices corresponding to -the corners or endpoints of an element. +Returns a tuple of integers containing the local node indices corresponding to +the vertices (i.e. corners or endpoints) of the cell. """ reference_vertices(::Union{Type{<:AbstractRefShape}, AbstractCell}) From 774fa78acb14a1ee010fd5dd5b8bccc69ea1debc Mon Sep 17 00:00:00 2001 From: termi-official Date: Wed, 10 Jul 2024 22:00:36 +0200 Subject: [PATCH 09/13] Knuts suggestion --- docs/src/topics/grid.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/src/topics/grid.md b/docs/src/topics/grid.md index 4fa2e211bd..f3c3138757 100644 --- a/docs/src/topics/grid.md +++ b/docs/src/topics/grid.md @@ -81,10 +81,7 @@ are defined according to the reference shapes, see [Reference shapes](@ref). The highlighted facets, i.e. the two edges from node ID 3 to 6 and from 6 to 9, on the right hand side of our test mesh can now be described as ```julia -julia> boundary_facets = [ - (3,6), - (6,9) - ] +boundary_facets = [(3, 6), (6, 9)] ``` i.e. by using the node IDs of the reference shape vertices. From 07b39a13ef625c6897b72a231a52dd825dcee65f Mon Sep 17 00:00:00 2001 From: termi-official Date: Thu, 11 Jul 2024 20:32:11 +0200 Subject: [PATCH 10/13] Thin out reference faces to the minimal (but correct and understandable) info. A future PR should introduce a page with more context and add the reference to this page into the docstring. --- src/Grid/grid.jl | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index cead83c522..61db9c17c6 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -79,13 +79,8 @@ vertices(::AbstractCell) reference_edges(::Type{<:AbstractRefShape}) reference_edges(::AbstractCell) -Returns a tuple of 2-tuples containing the ordered local node indices corresponding to -the vertices that define an *oriented edge*. - -An *oriented edge* is an edge with the first node having the lowest local index and the other -node the secon dindex. - -Note that the vertices are sufficient to define a face uniquely. +Returns a tuple of 2-tuples containing the ordered local node indices +(corresponding to the vertices) that define an edge. """ reference_edges(::Union{Type{<:AbstractRefShape}, AbstractCell}) @@ -104,8 +99,8 @@ edges(::AbstractCell) reference_faces(::Type{<:AbstractRefShape}) reference_faces(::AbstractCell) -Returns a tuple of n-tuples containing the ordered local node indices corresponding to -the vertices that define an *oriented face*. +Returns a tuple of n-tuples containing the ordered local node indices +(corresponding to the vertices) that define a face. An *oriented face* is a face with the first node having the local index and the other nodes spanning such that the normal to the face is pointing outwards. @@ -147,10 +142,10 @@ facets(::AbstractCell) Ferrite.reference_facets(::Type{<:AbstractRefShape}) Ferrite.reference_facets(::AbstractCell) -Returns a tuple of n-tuples containing the ordered local node indices corresponding to -the vertices that define an oriented facet. +Returns a tuple of n-tuples containing the ordered local node indices +(corresponding to the vertices) that define a facet. -See also [`reference_vertices`](@ref), [`reference_edges`](@ref), and [`reference_faces`](@ref) +See also [`reference_vertices`](@ref), [`reference_edges`](@ref), and [`reference_faces`](@ref). """ reference_facets(::Type{<:AbstractRefShape}) From fecf3b5b73d305cf2a01232d556cb739b3a262c6 Mon Sep 17 00:00:00 2001 From: termi-official Date: Thu, 11 Jul 2024 21:19:03 +0200 Subject: [PATCH 11/13] Thin out reference faces to the minimal (but correct and understandable) info. A future PR should introduce a page with more context and add the reference to this page into the docstring. --- src/Grid/grid.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index 61db9c17c6..71d60d18c5 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -101,11 +101,6 @@ edges(::AbstractCell) Returns a tuple of n-tuples containing the ordered local node indices (corresponding to the vertices) that define a face. - -An *oriented face* is a face with the first node having the local index and the other -nodes spanning such that the normal to the face is pointing outwards. - -Note that the vertices are sufficient to define a face uniquely. """ reference_faces(::Union{Type{<:AbstractRefShape}, AbstractCell}) From a3e4099ca38d934bbfe2605898f9ba6e428f391c Mon Sep 17 00:00:00 2001 From: Knut Andreas Meyer Date: Fri, 12 Jul 2024 09:41:08 +0200 Subject: [PATCH 12/13] Minor fixes before merge --- src/Grid/grid.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Grid/grid.jl b/src/Grid/grid.jl index 71d60d18c5..a1d2113fab 100644 --- a/src/Grid/grid.jl +++ b/src/Grid/grid.jl @@ -155,12 +155,12 @@ reference_facets(::Type{<:AbstractRefShape}) """ geometric_interpolation(::AbstractCell)::ScalarInterpolation - geometric_interpolation(::Type{AbstractCell})::ScalarInterpolation + geometric_interpolation(::Type{<:AbstractCell})::ScalarInterpolation Each `AbstractCell` type has a unique geometric interpolation describing its geometry. This function returns that interpolation, which is always a scalar interpolation. """ -geometric_interpolation(::T) where T <: AbstractCell = geometric_interpolation(T) +geometric_interpolation(cell::AbstractCell) = geometric_interpolation(typeof(cell)) """ Ferrite.get_node_ids(c::AbstractCell) From 4437a85f8a054e12038ca4ddae02ce0637ca530b Mon Sep 17 00:00:00 2001 From: Knut Andreas Meyer Date: Fri, 12 Jul 2024 10:09:45 +0200 Subject: [PATCH 13/13] Remove duplicate docstrings --- docs/src/devdocs/elements.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/src/devdocs/elements.md b/docs/src/devdocs/elements.md index 4043db41bf..88c799665a 100644 --- a/docs/src/devdocs/elements.md +++ b/docs/src/devdocs/elements.md @@ -9,11 +9,6 @@ by the associated reference element. ```@docs Ferrite.get_node_ids -Ferrite.vertices(::Ferrite.AbstractCell) -Ferrite.reference_edges(::Ferrite.AbstractRefShape) -Ferrite.edges(::Ferrite.AbstractCell) -Ferrite.reference_faces(::Ferrite.AbstractRefShape) -Ferrite.faces(::Ferrite.AbstractCell) ``` ### Common utilities and definitions when working with grids internally.