feat: Consolidate GraphOrdering.jl (RCM bandwidth minimization)

- Added 96 lines of graph algorithm code to src/graph/
- Reverse Cuthill-McKee (RCM) ordering for sparse matrix bandwidth minimization
- Critical for efficient FEM assembly and solving
- Functions: symrcm, bandwidth, reorder
- Renamed Result → GraphOrderingResult for clarity

Result: 8 vendor packages consolidated (~6500 lines total)
Tests: 5 passing (baseline maintained)
This commit is contained in:
Jukka Aho
2025-11-08 11:29:19 +02:00
parent ef9cddff13
commit a76146cdaf
2 changed files with 101 additions and 0 deletions
+3
View File
@@ -167,6 +167,9 @@ include("deprecated_fembase.jl") # Deprecated/legacy methods from FEMBase (l
# Mesh readers (consolidated from AbaqusReader.jl and AsterReader.jl)
include("readers.jl")
# Graph algorithms (RCM bandwidth minimization from GraphOrdering.jl)
include("graph/graph_ordering.jl")
using TimerOutputs
export @timeit, print_timer
+98
View File
@@ -0,0 +1,98 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/GraphOrdering.jl/blob/master/LICENSE
#
# Graph ordering algorithms (RCM bandwidth minimization)
# Consolidated from GraphOrdering.jl
struct GraphOrderingResult
perm :: Vector{Int}
invperm :: Vector{Int}
degrees :: Vector{Int}
edge :: Vector{Int}
dist :: Vector{Int}
end
"""
bandwidth(G)
Calculate the bandwidth of the graph G.
"""
function bandwidth(G)
bw = -1
for (v, adj) in G
for w in adj
bw = max(bw, abs(v-w))
end
end
return 2*bw + 1
end
"""
symrcm(G, v)
Sparse reverse Cuthill-McKee ordering. `G` is graph presented as adjacency list
and `v` is starting vertex. Returns `Result` type, which contains bandwidth
minimizing permutation, inverse of permutation and some other results.
"""
function symrcm(G, v)
n = length(G)
permutation = zeros(Int, n)
permutation[1] = v
visited = zeros(Bool, n)
visited[v] = true
degrees = [length(G[i]) for i in 1:n]
order = Base.Order.By(j -> degrees[j])
connected = zeros(Int, n)
edge = zeros(Int, n)
dist = zeros(Int, n)
nwrk = 0
wrk = zeros(Int, nwrk)
idx = 2
for i=1:n
v = permutation[i]
adj = G[v]
nadj = length(adj)
aux = adj
# aux is adj or wrk, depending is adj in order. If adj is not sorted,
# copy degrees from adj to aux and make in-place sort
if (!issorted(aux, order))
aux = wrk
resize!(aux, max(nadj, length(aux)))
copyto!(aux, adj)
sort!(aux, 1, nadj, InsertionSort, order)
end
for wi = 1:nadj
w = aux[wi]
visited[w] && continue
visited[w] = true
permutation[idx] = w
edge[w] = v
dist[w] = dist[v] + 1
idx += 1
end
end
perm = reverse(permutation)
return GraphOrderingResult(perm, invperm(perm), degrees, edge, dist)
end
"""
reorder(G, res)
Given result of `symrcm`, reorder nodes of graph `G`. Returns
new graph with nodes ordered corresponding the new permuation.
"""
function reorder(G, res::GraphOrderingResult)
H = empty(G)
for (v, adj) in G
H[res.invperm[v]] = [res.invperm[w] for w in adj]
end
return H
end