-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change parameterization of (Abstract)Cell #677
Comments
I agree that the parametrization is problematic. I have some experiments regarding a reparametrization here https://github.com/Ferrite-FEM/Ferrite.jl/pull/519/files#diff-aad722b9b915949ccae0c318858ae2725ae47adb50073f8b8d30092bffa1ac9f where I came to a similar conclusion. Here I have dropped the spatial dimension, but still have the number of nodes as type parameter. Dropping the number nodes is also an option. Still, I have a few questions here:
|
|
|
Then you could not use e.g. linear geometric interpolation with quadratic grid though? And you couldn't |
Wouldn't this break current assumptions as well, e.g. |
Okay, I thought that worked since all currently supported interpolations are hierarchical like that. |
|
I think, for example, that the implicit could theoretically cause ambiguity for some case of |
True, pretty much the only thing it is used for is to extract the coordinates.
We can keep linear and quadratic as special cases, and then if there is a need, implement a |
The simplicity of abstract type AbstractCell{refshape} end
struct Line <: AbstractCell{RefLine}
nodes::NTuple{2,Int}
end
struct Triangle <: AbstractCell{RefTriangle}
nodes::NTuple{3,Int}
end is tempting... Perhaps we can insert abstract type AbstractCell{refshape} end
abstract type LagrangeCell{refshape} <: AbstractCell{refshape} end
struct Line <: LagrangeCell{RefLine}
nodes::NTuple{2,Int}
end
struct Triangle <: LagrangeCell{RefTriangle}
nodes::NTuple{3,Int}
end ? |
I'm missing something, but I still don't follow the advantage of splitting up into multiple cell types, |
Using IP (or RefShape + N) as type parameter would solve e.g. the following issue with the latest version: struct QuadraticQuadrilateral <: LagrangeCell{RefQuad} or SerendipityCell{RefQuad}
nodes::NTuple{9 or 8,Int}
end (Which currently is Lagrange, but for e.g. importing Abaqus meshes, the standard quadratic quad is a Serendipity) |
The tuple size dont have to be a parameter, and it felt simpler to to squeeze it all into the same type.
Here I assumed that the name
|
Perhaps Lines 373 to 374 in aa26130
Here is my new suggestion then: No abstract types. The concrete built-in implementation # Abstract interface
abstract type AbstractCell end
get_geo_interpolation(::AbstractCell) = error("required method")
get_reference_dim(c::AbstractCell) = get_reference_dim(get_geo_interpolation(c))
get_reference_shape(c::AbstractCell) = get_reference_shape(get_geo_interpolation(c))
get_nodes(::AbstractCell) = error("required method")
# Concrete, built-in, implementation
struct Cell{IP <: Interpolation, N} <: AbstractCell
interpolation::IP
nodes::NTuple{N,Int}
end
get_geo_interpolation(c::Cell) = c.interpolation
get_nodes(c::Cell) = c.nodes
# Type aliases
const Line = Cell{Lagrange{1, RefCube, 1}, 2}
const QuadraticLine = Cell{Lagrange{2, RefTetrahedron, 2}, 3}
# etc |
I think we start to converge to a solution here. I like that it allows us to fix one specific geometric realization via an interpolation. A bit unfortunate that we still need the number of nodes as an extra parameter, although the information should already be contained in the interpolation implicitly. xref JuliaGeometry/GeometryBasics.jl#161 for more discussion regarding a general geometric interface for FE grids. I will try to bring this one forward together with @koehlerson on MakieCon next week. |
Sorry for being a bit late in to the discussion, but I dont really see the benefit with adding the interpolation as a type parameter and/or field variable. What is being improved with that approach, which we cant do with our current method i.e. I agree that our cell types can be improved in some way though (like getting rid of some ambiguities). But in that case I like the proposal with different struct for each celltype, e.g.
|
E.g. if your interpolation has some extra information, then |
@termi-official do you have an example of what type of information would be needed? We can probably replace # Entrypoint: Hook in here for AbstractCell implementation that needs information from the grid
get_geo_interpolation(grid::Grid, c::AbstractCell) = get_geo_interpolation(c)
# Hook in here for implementations that needs the nodes or other struct fields
get_geo_interpolation(c::AbstractCell) = get_geo_interpolation(typeof(c))
# Default stuff just like we have now
get_geo_interpolation(::Type{Line}) = Lagrange{1,RefCube,1}() |
A (rather stupid) example would be high order Lagrange basis functions (thing e.g. about P adaptivity). We can automatically construct these from a given node set. In this case some of this nodal information is stored in the interpolation. I mean, we might still be able to fix this with more type parameters and reconstruction the interpolation every time we call |
@termi-official I think you mentioned Hermite polynomials vs Lagrange as a potential source of ambiguity? I think all discussed options solve these issues. Certainly, a specific type for each cell cannot go wrong wrt. generality, but the biggest con I see is that there will be a lot of code duplication. For example, all types would have to implement At least for Lagrange and Serendipity interpolations, the structure would look the same. I'm not sure how that would be with Hermite though? If we restrict * |
Hermite is at least an obvious one, this is why I like to take it as an example (c.f. https://defelement.com/elements/examples/triangle-Hermite-3.html and e.g. https://defelement.com/elements/examples/triangle-bubble-enriched-Lagrange-1.html which have both 4 nodes. Or even on segments. Regarding the transformations, I think we require H2 conformity, which I am not sure how to enforce correctly. Technically this can be even currently resolved by "just" defining a new |
The Hermite-3 is a good example of challenging the question of whether it suffices to have only nodes as the cell information! Spontaneously, I would guess that a new type of node (containing at least one position and two rotations (probably including redundant direction information for easier implementation)) would be required for the vertices. If I understand correctly, we have 4 points and 6 rotation angles. So from that point of view, it couldn't even be solved locally on the cell level? |
We probably want to follow existing theory for now. I think [1] is a good start. [1] Kirby, Robert C. "A general approach to transforming finite elements." The SMAI journal of computational mathematics 4 (2018): 197-224. |
"In contrast to the Lagrange element, its [Hermite. my note] node set includes function values and derivatives at the nodes, as well as an interior function value" [1] Yes, wouldn't that be the case? (2d-gradient ~ 2 rotation angles)? (But of course a bit more challenging to implement in practice:)) |
(I started writing this yesterday so you have already discussed some of these things)
All built in cell types could have the same
I don't like this because how do you easily connect that e.g. struct Line ... end or const Line = Cell{Lagrange{1,RefCube,1}, 2} and that doesn't seem to matter much IMO. I think I would favor the explicit Line struct since it doesn't have the tuple-size as a parameter. Using vertices(c::Cell{Serendipity{2,RefCube,2}, 8}) = # ...
edges(c::Cell{Serendipity{2,RefCube,2}, 8}) = # ...
faces(c::Cell{Serendipity{2,RefCube,2}, 8}) = # ... and I am not sure writing |
OK, I thought one could do, e.g. Edit: But I guess that would still be possible with separate structs, just by calling |
This patch reworks the `AbstractCell` interface (refer to #677 for motivation and discussion for alternatives to this patch). Specifically, this patch - introduces the reference dimension as a type parameter on `AbstractRefShape`, - introduces `RefInterval`, `RefTriangle`, `RefQuadrilateral`, and `RefHexahedron` as new subtypes of `AbstractRefShape{refdim}` (note that interpolations are not updated to this system yet since it can be done in a separate patch), - deprecates the old `Cell{refdim, nnodes, nfaces}` struct, - introduces new structs for all supported cell types, e.g. `struct Triangle <: AbstractCell{RefTriangle}`, - defines the unique vertex/edge/face identifiers for DoF-distribution in terms of the reference shape. The new parametrization makes it possible to dispatch on the reference shape instead of union of concrete implementations, i.e. `::AbstractCell{RefTriangle}` instead of `::Union{Triangle, QuadraticTriangle}`, and similarly for the reference dimension. One drawback is that it is no longer possible to use "anonymous celltypes" after this patch, i.e. using, e.g., `Cell{3, 20, 6}` and defining methods for that instead of explicitly naming it `SerendipityQuadraticHexahedron` or similar. Instead, you now have to define a struct and some methods. Arguably this is a good thing -- nobody understands the meaning of `Cell{3, 20, 6}`. For normal usage this patch is not breaking (see e.g. no required changes for examples), unless one dispatches on the `Cell` struct directly. Specific things that remain to be decided: - `struct Triangle <: AbstractCell{2, RefTriangle}` or `struct Triangle <: AbstractRefCell{2, RefTriangle} <: AbstractCell`? I don't know if it is too restrictive to "force" `{refdim, refshape}` on all subtypes of `AbstractCell`. On the other hand, if one implements a non-refshape based element one can define a dummy reference shape. For a real-world example, looking at e.g. https://github.com/kimauth/FerriteCohesiveZones.jl/blob/main/src/cohesive_cell.jl I think that would simply be implemented as ```julia struct CohesiveQuadrilateral <: AbstractCell{2, RefQuadrilateral} nodes::NTuple{4, Int} end ``` which I don't see a direct problem with, other than the fact that the cell will now have 4 edges (according to the fallback definitions). To solve this, one would have to implement a method for `faces(::CohesiveQuadrilateral)` that only return the upper and lower edge. I don't think this is too much to ask for custom elements like this. Alternatively, with #581 merged it is possible to distribute different number of dofs for different edges, so this can also be solved on the (default) interpolation level by distributing 0 dofs on the left and right edge. - `AbstractCell{refdim, refshape}` or just `AbstractCell{refshape}`? The dimension is implicit from the shape now, and you can dispatch on `AbstractCell{<:AbstractRefShape{refdim}} where refdim`. Personally I am in favor of including the dimension, even if redundant. It does not cost anything, and sometimes you want to dispatch on the dimension, sometimes on the refshape. Fixes #677.
This patch reworks the `AbstractCell` interface (refer to #677 for motivation and discussion for alternatives to this patch). Specifically, this patch - introduces the reference dimension as a type parameter on `AbstractRefShape`, - introduces `RefInterval`, `RefTriangle`, `RefQuadrilateral`, and `RefHexahedron` as new subtypes of `AbstractRefShape{refdim}` (note that interpolations are not updated to this system yet since it can be done in a separate patch), - deprecates the old `Cell{refdim, nnodes, nfaces}` struct, - introduces new structs for all supported cell types, e.g. `struct Triangle <: AbstractCell{2, RefTriangle}`, - defines the unique vertex/edge/face identifiers for DoF-distribution in terms of the reference shape. The new parametrization makes it possible to dispatch on the reference shape instead of union of concrete implementations, i.e. `::AbstractCell{2, RefTriangle}` instead of `::Union{Triangle, QuadraticTriangle}`, and similarly for the reference dimension. One drawback is that it is no longer possible to use "anonymous celltypes" after this patch, i.e. using, e.g., `Cell{3, 20, 6}` and defining methods for that instead of explicitly naming it `SerendipityQuadraticHexahedron` or similar. Instead, you now have to define a struct and some methods. Arguably this is a good thing -- nobody understands the meaning of `Cell{3, 20, 6}`. For normal usage this patch is not breaking (see e.g. no required changes for examples), unless one dispatches on the `Cell` struct directly. Fixes #677.
This patch reworks the `AbstractCell` interface (refer to #677 for motivation and discussion for alternatives to this patch). Specifically, this patch - introduces the reference dimension as a type parameter on `AbstractRefShape`, - introduces `RefLine`, `RefTriangle`, `RefQuadrilateral`, and `RefHexahedron` as new subtypes of `AbstractRefShape{refdim}` (note that interpolations are not updated to this system yet since it can be done in a separate patch), - deprecates the old `Cell{refdim, nnodes, nfaces}` struct, - introduces new individual structs for all supported cell types, e.g. `struct Triangle <: AbstractCell{2, RefTriangle}`, - defines the unique vertex/edge/face identifiers for DoF-distribution in terms of dispatch on the reference shape. The new parametrization makes it possible to dispatch on the reference shape instead of union of concrete implementations, i.e. `::AbstractCell{2, RefTriangle}` instead of `::Union{Triangle, QuadraticTriangle}`, and similarly for the reference dimension. One drawback is that it is no longer possible to use "anonymous celltypes" after this patch, i.e. using, e.g., `Cell{3, 20, 6}` and defining methods for that instead of explicitly naming it `SerendipityQuadraticHexahedron` or similar. Instead, you now have to define a struct and some methods. Arguably this is a good thing -- nobody understands the meaning of `Cell{3, 20, 6}`. For normal usage this patch is not breaking (see e.g. no required changes for examples), unless one dispatches on the `Cell` struct directly. Fixes #677.
This patch reworks the `AbstractCell` interface (refer to #677 for motivation and discussion for alternatives to this patch). Specifically, this patch - introduces the reference dimension as a type parameter on `AbstractRefShape`, - introduces `RefLine`, `RefTriangle`, `RefQuadrilateral`, and `RefHexahedron` as new subtypes of `AbstractRefShape{refdim}` (note that interpolations are not updated to this system yet since it can be done in a separate patch), - deprecates the old `Cell{refdim, nnodes, nfaces}` struct, - introduces new individual structs for all supported cell types, e.g. `struct Triangle <: AbstractCell{2, RefTriangle}`, - defines the unique vertex/edge/face identifiers for DoF-distribution in terms of dispatch on the reference shape. The new parametrization makes it possible to dispatch on the reference shape instead of union of concrete implementations, i.e. `::AbstractCell{2, RefTriangle}` instead of `::Union{Triangle, QuadraticTriangle}`, and similarly for the reference dimension. One drawback is that it is no longer possible to use "anonymous celltypes" after this patch, i.e. using, e.g., `Cell{3, 20, 6}` and defining methods for that instead of explicitly naming it `SerendipityQuadraticHexahedron` or similar. Instead, you now have to define a struct and some methods. Arguably this is a good thing -- nobody understands the meaning of `Cell{3, 20, 6}`. For normal usage this patch is not breaking (see e.g. no required changes for examples), unless one dispatches on the `Cell` struct directly. Fixes #677.
Currently we have
Ferrite.jl/src/Grid/grid.jl
Line 25 in aa26130
Ferrite.jl/src/Grid/grid.jl
Lines 37 to 39 in aa26130
M
, shouldn't be a type parameter. It is not required for the storage (i.e. anNTuple
or similar) and we never use it for dispatch. It was introduced in Lots of stuff... #125 because at the time we stored anM
-tuple with on-boundary info. This struct field was removed in store boundaries in a matrix #130, but not the type parameter. In Changes to MixedDofHandler #279 theAbstractCell
was introduced, and that propagatedM
also to the abstract type.Ferrite.jl/src/Grid/grid.jl
Lines 85 to 106 in aa26130
Here is a suggested re-parametrization:
Line{spacedim}
can then replaceLine
,Line2D
andLine3D
, for example.For the grid, all cells would have the same spacedim (i.e. the dim of the grid). In the grid:
when mixing cell types, for example
Triangle
s andQuadrilateral
s, we would then go fromto
which shouldn't matter to the compiler (but let's benchmark).
The text was updated successfully, but these errors were encountered: