From 1b18af15a17c7314ed91f15075c62bd07d526cc0 Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Sat, 15 Nov 2025 18:44:48 +0200 Subject: [PATCH] refactor(topology): Move interface to topology/api.jl, keep helpers in topology.jl Refactor src/topology/topology.jl from 173 to 12 lines: - Remove all AbstractTopology{N} interface definitions (161 lines removed) - Remove nnodes(), dim(), reference_coordinates(), edges(), faces() stubs - Interface now defined in src/topology/api.jl (included first) - Keep file as placeholder for future helper functions - Add note referencing topology/api.jl for interface This completes separation of interface (api.jl) from implementations. Topology/topology.jl previously mixed interface and helpers - now clean separation following systematic modular architecture pattern. Part of systematic modular API refactoring. --- src/topology/topology.jl | 161 ++------------------------------------- 1 file changed, 6 insertions(+), 155 deletions(-) diff --git a/src/topology/topology.jl b/src/topology/topology.jl index 55b2349..8fbff17 100644 --- a/src/topology/topology.jl +++ b/src/topology/topology.jl @@ -2,161 +2,12 @@ # License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md """ - AbstractTopology +Topology module - concrete implementations. -Abstract base type for all reference element topologies. - -**IMPORTANT SEPARATION OF CONCERNS:** -- **Topology** = Geometric shape (e.g., Triangle, Quadrilateral, Tetrahedron) -- **Basis** = Interpolation scheme (e.g., Lagrange{Triangle, 1}, Serendipity{Quadrilateral, 2}) -- **Node count** comes from BASIS, not topology! - -A topology defines the **combinatorial structure** of how corner nodes connect to form -an element in parametric (reference) coordinates. Topologies are **mathematical shapes** -independent of interpolation schemes or integration rules. - -# Key Properties -- Spatial dimension (1D, 2D, 3D) -- Number of **corner** nodes -- Reference element geometry (corner positions only) -- Edge and face connectivity (corner nodes only) -- Node ordering convention - -# Topology vs Node Count - -The same topology supports different node counts via different basis functions: - -```julia -# Same topology (Quadrilateral), different node counts: -Lagrange{Quadrilateral, 1} → 4 nodes (bilinear) -Serendipity{Quadrilateral, 2} → 8 nodes (no center) -Lagrange{Quadrilateral, 2} → 9 nodes (with center) -``` - -# Examples -```julia -# New API (explicit separation) -topology = Triangle() -basis = Lagrange{Triangle, 1}() -element = Element(basis, (1,2,3)) - -# Old API (deprecated, but still works via aliases) -element = Element(Tri3, (1,2,3)) # Tri3 is alias for Triangle -``` - -See also: [`Segment`](@ref), [`Triangle`](@ref), [`Quadrilateral`](@ref), - [`Tetrahedron`](@ref), [`Hexahedron`](@ref), [`Pyramid`](@ref), [`Wedge`](@ref) - -# Type Parameter - -`AbstractTopology{N}` where `N` is the number of nodes. Node count comes from mesh connectivity. - -# Examples -```julia -Hexahedron{8} <: AbstractTopology{8} # 8-node hex (linear) -Hexahedron{20} <: AbstractTopology{20} # 20-node hex (quadratic serendipity) -Hexahedron{27} <: AbstractTopology{27} # 27-node hex (quadratic full) -``` - -# Rationale - -Node count is included in the type parameter for compile-time performance optimization: -- Enables `Val(N)` for zero-allocation ntuple operations -- Allows loop unrolling for small N -- Node count comes from mesh connectivity, not basis choice -- See ADR-002 for detailed design rationale +Abstract type and interface are defined in topology/api.jl. +This file is kept for backward compatibility and to provide any +additional helper functions beyond the core API. """ -abstract type AbstractTopology{N} end -""" - nnodes(topology::AbstractTopology) -> Int - -Return the number of nodes in the reference element. - -# Examples -```julia -julia> nnodes(Tri3()) -3 - -julia> nnodes(Hex8()) -8 -``` -""" -function nnodes end - -""" - dim(topology::AbstractTopology) -> Int - -Return the spatial dimension of the reference element (1, 2, or 3). - -# Examples -```julia -julia> dim(Tri3()) -2 - -julia> dim(Hex8()) -3 -``` -""" -function dim end - -""" - reference_coordinates(topology::AbstractTopology) -> NTuple{N, NTuple{D, Float64}} - -Return the coordinates of nodes in the reference element as a tuple of tuples. - -**Zero allocation:** Returns compile-time sized tuple, fully stack allocated. - -# Convention -Reference elements are defined in parametric coordinates ξ ∈ [-1, 1]^D (for most elements). - -# Examples -```julia -julia> reference_coordinates(Tri3()) -((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)) - -julia> typeof(reference_coordinates(Tri3())) -NTuple{3, NTuple{2, Float64}} -``` -""" -function reference_coordinates end - -""" - faces(topology::AbstractTopology) -> NTuple{Nf, NTuple{Nn, Int}} - -Return the connectivity of faces for the reference element as a tuple of tuples. - -Each face is represented as a tuple of local node indices (1-based). - -**Zero allocation:** Returns compile-time sized nested tuple, fully stack allocated. - -# Examples -```julia -julia> faces(Quad4()) -((1, 2, 3, 4),) # 2D element has one face (itself) - -julia> faces(Hex8()) -((1, 4, 3, 2), (5, 6, 7, 8), (1, 2, 6, 5), (2, 3, 7, 6), (3, 4, 8, 7), (4, 1, 5, 8)) -``` -""" -function faces end - -""" - edges(topology::AbstractTopology) -> NTuple{Ne, Tuple{Int, Int}} - -Return the connectivity of edges for the reference element as a tuple of tuples. - -Each edge is represented as a tuple of two local node indices (1-based). - -**Zero allocation:** Returns compile-time sized tuple, fully stack allocated. - -# Examples -```julia -julia> edges(Tri3()) -((1, 2), (2, 3), (3, 1)) - -julia> typeof(edges(Tri3())) -NTuple{3, Tuple{Int64, Int64}} -``` -""" -function edges end +# NOTE: AbstractTopology{N} and interface functions (nnodes, dim, reference_coordinates, edges, faces) +# are now defined in topology/api.jl, which is included before this file in JuliaFEM.jl