Skip to content

Commit 950a514

Browse files
author
Sebastien Loisel
committed
Remove the derivable Geometry.subspaces field
The single-level Geometry.subspaces Dict was consumed only by amg, for the fine-level :full / :uniform embeddings — which are exactly I(n_doubled) and ones(n_doubled, 1). Derive them in _assemble_amg_dicts instead and drop the field plus its M_sub type parameter. Updates every Geometry{...} signature (the M_sub slot, always just before the discretization parameter, is removed), all construction sites (dropping both the type parameter and the subspaces argument), the now-dead single-level subspace dicts in the mesh constructors, and the CUDA-extension Geometry conversions. MultiGrid.subspaces (the per-level hierarchy) is unchanged; spectral amg never read the field.
1 parent dadc4a0 commit 950a514

13 files changed

Lines changed: 90 additions & 164 deletions

File tree

ext/MultiGridBarrierCUDAExt/block_ops.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,8 +1264,8 @@ function MultiGridBarrier._structurize_multigrid(
12641264
XT = typeof(geom.x); WT = typeof(geom.w)
12651265
M_op_type = valtype(operators_new)
12661266
DiscT = typeof(geom.discretization)
1267-
new_geom = MultiGridBarrier.Geometry{T,XT,WT,M_op_type,M_sub,DiscT}(
1268-
geom.discretization, geom.x, geom.w, geom.subspaces, operators_new)
1267+
new_geom = MultiGridBarrier.Geometry{T,XT,WT,M_op_type,DiscT}(
1268+
geom.discretization, geom.x, geom.w, operators_new)
12691269

12701270
return MultiGridBarrier.MultiGrid(new_geom, subspaces_new, refine_new, coarsen_new)
12711271
end

ext/MultiGridBarrierCUDAExt/conversion.jl

Lines changed: 17 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Convert a native (CPU) `Geometry` to CUDA GPU types.
3636
- `SparseMatrixCSC{T,Int}` → `CuSparseMatrixCSR{T,Int32}`
3737
- Dense `Matrix{T}` operators → `CuMatrix{T}` (spectral)
3838
"""
39-
function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Int}, SparseMatrixCSC{T,Int}, Discretization};
39+
function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Int}, Discretization};
4040
Ti::Type{<:Integer}=Int32) where {T, Discretization}
4141
x_cuda = CuArray{T,3}(g.x)
4242
w_cuda = CuVector{T}(g.w)
@@ -51,21 +51,15 @@ function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, S
5151
operators_cuda[key] = convert_sparse(g.operators[key])
5252
end
5353

54-
subspaces_cuda = Dict{Symbol, MType}()
55-
for key in sort(collect(keys(g.subspaces)))
56-
subspaces_cuda[key] = convert_sparse(g.subspaces[key])
57-
end
58-
59-
Geometry{T, CuArray{T,3}, CuVector{T}, MType, MType, Discretization}(
60-
g.discretization, x_cuda, w_cuda, subspaces_cuda, operators_cuda)
54+
Geometry{T, CuArray{T,3}, CuVector{T}, MType, Discretization}(
55+
g.discretization, x_cuda, w_cuda, operators_cuda)
6156
end
6257

6358
# BlockDiag-operator variant: FEM Geometry whose `operators` came in via
6459
# `subdivide` (or `geometric_mg(...; structured=true).geometry`). Carry the
6560
# BlockDiag to GPU as a CuArray-backed BlockDiag; subspaces stay sparse CSR.
6661
function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T},
6762
MultiGridBarrier.BlockDiag{T, A3},
68-
SparseMatrixCSC{T,Int},
6963
Discretization};
7064
Ti::Type{<:Integer}=Int32) where {T, A3<:Array{T,3}, Discretization}
7165
x_cuda = CuArray{T,3}(g.x)
@@ -76,24 +70,18 @@ function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T},
7670
MultiGridBarrier.BlockDiag{T, typeof(gpu_data)}(op.p, op.q, op.N, gpu_data)
7771
end
7872

79-
sparse_to_gpu = op -> CuSparseMatrixCSR(
80-
SparseMatrixCSC{T,Ti}(op.m, op.n, Ti.(op.colptr), Ti.(op.rowval), op.nzval))
81-
8273
sample_op = op_to_gpu(first(values(g.operators)))
8374
OpType = typeof(sample_op)
84-
SubType = CuSparseMatrixCSR{T,Ti}
8575

8676
operators_cuda = Dict{Symbol, OpType}(
8777
key => op_to_gpu(g.operators[key]) for key in keys(g.operators))
88-
subspaces_cuda = Dict{Symbol, SubType}(
89-
key => sparse_to_gpu(g.subspaces[key]) for key in keys(g.subspaces))
9078

91-
Geometry{T, CuArray{T,3}, CuVector{T}, OpType, SubType, Discretization}(
92-
g.discretization, x_cuda, w_cuda, subspaces_cuda, operators_cuda)
79+
Geometry{T, CuArray{T,3}, CuVector{T}, OpType, Discretization}(
80+
g.discretization, x_cuda, w_cuda, operators_cuda)
9381
end
9482

9583
# Dense spectral variant.
96-
function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, Matrix{T}, Matrix{T}, Discretization};
84+
function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, Matrix{T}, Discretization};
9785
kwargs...) where {T, Discretization}
9886
x_cuda = CuArray{T,3}(g.x)
9987
w_cuda = CuVector{T}(g.w)
@@ -103,13 +91,8 @@ function MultiGridBarrier.native_to_cuda(g::Geometry{T, Array{T,3}, Vector{T}, M
10391
operators_cuda[key] = CuMatrix{T}(g.operators[key])
10492
end
10593

106-
subspaces_cuda = Dict{Symbol, CuMatrix{T}}()
107-
for key in sort(collect(keys(g.subspaces)))
108-
subspaces_cuda[key] = CuMatrix{T}(g.subspaces[key])
109-
end
110-
111-
Geometry{T, CuArray{T,3}, CuVector{T}, CuMatrix{T}, CuMatrix{T}, Discretization}(
112-
g.discretization, x_cuda, w_cuda, subspaces_cuda, operators_cuda)
94+
Geometry{T, CuArray{T,3}, CuVector{T}, CuMatrix{T}, Discretization}(
95+
g.discretization, x_cuda, w_cuda, operators_cuda)
11396
end
11497

11598
# ============================================================================
@@ -204,7 +187,7 @@ end
204187

205188
# Sparse FEM Geometry (CSR operators).
206189
function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVector{T},
207-
<:CuSparseMatrixCSR{T}, <:CuSparseMatrixCSR{T},
190+
<:CuSparseMatrixCSR{T},
208191
Discretization}) where {T, Discretization}
209192
x_native = Array{T,3}(Array(g.x))
210193
w_native = Vector{T}(Array(g.w))
@@ -219,18 +202,13 @@ function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVect
219202
operators_native[key] = convert_back(g.operators[key])
220203
end
221204

222-
subspaces_native = Dict{Symbol, SparseMatrixCSC{T,Ti}}()
223-
for key in sort(collect(keys(g.subspaces)))
224-
subspaces_native[key] = convert_back(g.subspaces[key])
225-
end
226-
227-
Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Ti}, SparseMatrixCSC{T,Ti}, Discretization}(
228-
g.discretization, x_native, w_native, subspaces_native, operators_native)
205+
Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Ti}, Discretization}(
206+
g.discretization, x_native, w_native, operators_native)
229207
end
230208

231209
# Dense spectral Geometry.
232210
function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVector{T},
233-
<:CuMatrix{T}, <:CuMatrix{T},
211+
<:CuMatrix{T},
234212
Discretization}) where {T, Discretization}
235213
x_native = Array{T,3}(Array(g.x))
236214
w_native = Vector{T}(Array(g.w))
@@ -240,18 +218,13 @@ function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVect
240218
operators_native[key] = Matrix{T}(Array(g.operators[key]))
241219
end
242220

243-
subspaces_native = Dict{Symbol, Matrix{T}}()
244-
for key in sort(collect(keys(g.subspaces)))
245-
subspaces_native[key] = Matrix{T}(Array(g.subspaces[key]))
246-
end
247-
248-
Geometry{T, Array{T,3}, Vector{T}, Matrix{T}, Matrix{T}, Discretization}(
249-
g.discretization, x_native, w_native, subspaces_native, operators_native)
221+
Geometry{T, Array{T,3}, Vector{T}, Matrix{T}, Discretization}(
222+
g.discretization, x_native, w_native, operators_native)
250223
end
251224

252225
# Structured FEM Geometry (block ops).
253226
function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVector{T},
254-
<:Any, <:Any, Discretization}) where {T, Discretization}
227+
<:Any, Discretization}) where {T, Discretization}
255228
x_native = Array{T,3}(Array(g.x))
256229
w_native = Vector{T}(Array(g.w))
257230

@@ -267,13 +240,8 @@ function MultiGridBarrier.cuda_to_native(g::Geometry{T, <:CuArray{T,3}, <:CuVect
267240
operators_native[key] = convert_to_native(g.operators[key])
268241
end
269242

270-
subspaces_native = Dict{Symbol, SparseMatrixCSC{T,Ti}}()
271-
for key in sort(collect(keys(g.subspaces)))
272-
subspaces_native[key] = convert_to_native(g.subspaces[key])
273-
end
274-
275-
Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Ti}, SparseMatrixCSC{T,Ti}, Discretization}(
276-
g.discretization, x_native, w_native, subspaces_native, operators_native)
243+
Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Ti}, Discretization}(
244+
g.discretization, x_native, w_native, operators_native)
277245
end
278246

279247
# MultiGrid cuda → native (sparse FEM).

src/AlgebraicMultiGridBarrier.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ Base.showerror(io::IO, e::MGBConvergenceFailure) = print(io, "MGBConvergenceFail
203203
end
204204

205205
"""
206-
Geometry{T,X<:AbstractArray{T,3},W,M_op,M_sub,Discretization}
206+
Geometry{T,X<:AbstractArray{T,3},W,M_op,Discretization}
207207
208208
Single-level container for discretization geometry. Holds only the fine-level mesh and
209209
operators — no multigrid hierarchy. Use `amg(geom)` to attach an algebraic-multigrid
@@ -215,7 +215,6 @@ Type parameters
215215
- `X<:AbstractArray{T,3}`: type of the mesh tensor `x` (typically `Array{T,3}`).
216216
- `W`: type of the weight storage `w` (typically `Vector{T}`).
217217
- `M_op`: matrix type for operators (e.g. `SparseMatrixCSC{T,Int}`, `BlockDiag{T}`).
218-
- `M_sub`: matrix type for subspace embeddings (e.g. `SparseMatrixCSC{T,Int}`).
219218
- `Discretization`: front-end descriptor (e.g. `FEM1D{T}`, `FEM2D_P2{T}`, `SPECTRAL1D{T}`).
220219
221220
Fields
@@ -225,14 +224,12 @@ Fields
225224
flat layout via `reshape(x, V*N, D)` (zero-copy). Spectral discretizations
226225
use `N = 1` (a single notional "element" comprising every Chebyshev node).
227226
- `w::W`: quadrature weights matching the flattened node order (length `V*N`).
228-
- `subspaces::Dict{Symbol,M_sub}`: fine-level selection/embedding matrices (one per symbol).
229227
- `operators::Dict{Symbol,M_op}`: fine-level discrete operators (e.g. `:id`, `:dx`, `:dy`).
230228
"""
231-
struct Geometry{T,X<:AbstractArray{T,3},W,M_op,M_sub,Discretization}
229+
struct Geometry{T,X<:AbstractArray{T,3},W,M_op,Discretization}
232230
discretization::Discretization
233231
x::X
234232
w::W
235-
subspaces::Dict{Symbol,M_sub}
236233
operators::Dict{Symbol,M_op}
237234
end
238235

@@ -532,7 +529,7 @@ function amg end
532529
# nominally rides is immaterial. Each `(sym, nodes)` entry of `dirichlet_nodes`
533530
# adds one zero-trace continuous subspace built by the discretization-specific
534531
# `build_dirichlet(nodes) -> (refine, coarsen, sub)` closure.
535-
function _assemble_amg_dicts(::Type{T}, geom,
532+
function _assemble_amg_dicts(::Type{T}, geom, n_doubled::Int,
536533
dirichlet_nodes::Dict{Symbol,Vector{Tuple{Int,Int}}},
537534
refine_full::Vector{SparseMatrixCSC{T,Int}},
538535
coarsen_full::Vector{SparseMatrixCSC{T,Int}},
@@ -544,8 +541,11 @@ function _assemble_amg_dicts(::Type{T}, geom,
544541
sub_full[kk] = sparse(one(T) * I, sizes_full[kk], sizes_full[kk])
545542
sub_uniform[kk] = sparse(ones(T, sizes_full[kk], 1))
546543
end
547-
sub_full[L_full] = SparseMatrixCSC{T,Int}(geom.subspaces[:full])
548-
sub_uniform[L_full] = SparseMatrixCSC{T,Int}(geom.subspaces[:uniform])
544+
# Fine-level (level-L) embeddings: `:full` is the entire broken space
545+
# (identity) and `:uniform` is the constant column. Both depend only on the
546+
# broken-DOF count `n_doubled`.
547+
sub_full[L_full] = sparse(one(T) * I, n_doubled, n_doubled)
548+
sub_uniform[L_full] = sparse(ones(T, n_doubled, 1))
549549

550550
subspaces = Dict{Symbol,Vector{SparseMatrixCSC{T,Int}}}(:full => sub_full, :uniform => sub_uniform)
551551
refine_d = Dict{Symbol,Vector{SparseMatrixCSC{T,Int}}}(:full => refine_full, :uniform => refine_full)
@@ -2608,7 +2608,7 @@ struct MGBSOL{T,X,W,Discretization,G}
26082608
log::String
26092609
geometry::G
26102610
end
2611-
function MGBSOL(z::X, sf, sm, log::String, geometry::Geometry{T,<:Any,W,<:Any,<:Any,Discretization}) where {T,X,W,Discretization}
2611+
function MGBSOL(z::X, sf, sm, log::String, geometry::Geometry{T,<:Any,W,<:Any,Discretization}) where {T,X,W,Discretization}
26122612
MGBSOL{T,X,W,Discretization,typeof(geometry)}(z, sf, sm, log, geometry)
26132613
end
26142614
plot(sol::MGBSOL,k::Int=1;kwargs...) = plot(sol.geometry,sol.z[:,k];kwargs...)

src/BlockMatrices.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,10 +1110,10 @@ end
11101110
function _default_block_size end
11111111

11121112
# Rebuild a Geometry with a new (structured) operators dict, preserving everything else.
1113-
function _replace_operators(geom::Geometry{T,X,W,<:Any,M_sub,Disc},
1114-
operators_new::Dict{Symbol,M_op_new}) where {T,X,W,M_sub,Disc,M_op_new}
1115-
Geometry{T,X,W,M_op_new,M_sub,Disc}(
1116-
geom.discretization, geom.x, geom.w, geom.subspaces, operators_new)
1113+
function _replace_operators(geom::Geometry{T,X,W,<:Any,Disc},
1114+
operators_new::Dict{Symbol,M_op_new}) where {T,X,W,Disc,M_op_new}
1115+
Geometry{T,X,W,M_op_new,Disc}(
1116+
geom.discretization, geom.x, geom.w, operators_new)
11171117
end
11181118

11191119
# Structurize a MultiGrid: convert geometry's operators to BlockDiag,

src/Mesh3d/Geometry.jl

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,10 @@ function _geometric_fem3d_mg(::Type{T}=Float64; L::Int=2,
126126
end
127127

128128
x_fine = reshape(meshes[L], sk3, N_fine, 3)
129-
geom = Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Int}, SparseMatrixCSC{T,Int}, FEM3D{T}}(
129+
geom = Geometry{T, Array{T,3}, Vector{T}, SparseMatrixCSC{T,Int}, FEM3D{T}}(
130130
disc,
131131
x_fine,
132132
weights[L],
133-
Dict{Symbol,SparseMatrixCSC{T,Int}}(
134-
:full => subspaces[:full][end],
135-
:uniform => subspaces[:uniform][end],
136-
:dirichlet => subspaces[:dirichlet][end]),
137133
ops,
138134
)
139135
return MultiGrid(geom, subspaces, refine_ops, coarsen_ops)
@@ -270,14 +266,8 @@ function _fem3d_structured(disc::FEM3D{T}, meshes, weights, L, k, ref_el) where
270266
s_ = k + 1
271267
sk3_ = s_^3
272268
x_fine = reshape(meshes[L], sk3_, div(size(meshes[L], 1), sk3_), 3)
273-
geom = Geometry{T, Array{T,3}, Vector{T}, BlockDiag{T,Array{T,3}},
274-
SparseMatrixCSC{T,Int}, FEM3D{T}}(
275-
disc, x_fine, weights[L],
276-
Dict{Symbol,SparseMatrixCSC{T,Int}}(
277-
:full => subspaces[:full][end],
278-
:uniform => subspaces[:uniform][end],
279-
:dirichlet => subspaces[:dirichlet][end]),
280-
operators)
269+
geom = Geometry{T, Array{T,3}, Vector{T}, BlockDiag{T,Array{T,3}}, FEM3D{T}}(
270+
disc, x_fine, weights[L], operators)
281271
return MultiGrid(geom, subspaces, refine, coarsen)
282272
end
283273

@@ -388,7 +378,7 @@ end
388378
Evaluate the finite element field `u` at point `x_eval`. Returns the value and a flag
389379
indicating whether the point was found.
390380
"""
391-
function evaluate_field(g::Geometry{T,X,W,<:Any,<:Any,FEM3D{T}}, u::Vector{T}, x_eval::Vector{T}) where {T,X,W}
381+
function evaluate_field(g::Geometry{T,X,W,<:Any,FEM3D{T}}, u::Vector{T}, x_eval::Vector{T}) where {T,X,W}
392382
k = g.discretization.k
393383
n_nodes_per_elem = (k+1)^3
394384
x_flat = _xflat(g.x)

src/Mesh3d/Plotting.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ plot(sol; slice=(normal=[1,1,1], origin=[0,0,0]))
9797
plot(sol; plotter=(window_size=(1600, 1200),))
9898
```
9999
"""
100-
function plot(geo::Geometry{T,X,W,<:Any,<:Any,FEM3D{T}}, u::Vector{T};
100+
function plot(geo::Geometry{T,X,W,<:Any,FEM3D{T}}, u::Vector{T};
101101
plotter::NamedTuple=(window_size=(800, 600),),
102102
volume=(;),
103103
scalar_bar_args=(title="",position_x=0.6,position_y=0.0,width=0.35,height=0.05,use_opacity=false),
@@ -269,7 +269,7 @@ function create_vtk_cells(k::Int, n_total_nodes::Int)
269269
end
270270

271271
"""
272-
plot(M::Geometry{T,X,W,<:Any,<:Any,FEM3D{T}}, ts::AbstractVector, U::Matrix{T}; kwargs...)
272+
plot(M::Geometry{T,X,W,<:Any,FEM3D{T}}, ts::AbstractVector, U::Matrix{T}; kwargs...)
273273
274274
Create an animated 3D visualization from a time series of solutions.
275275
@@ -293,7 +293,7 @@ base64-encoded data in an HTML5 video tag.
293293
Color limits (`clim`) and `isosurfaces` are automatically computed from the global
294294
range of U across all frames to ensure consistent visualization throughout the animation.
295295
"""
296-
function plot(M::Geometry{T,X,W,<:Any,<:Any,FEM3D{T}}, ts::AbstractVector, U::Matrix{T};
296+
function plot(M::Geometry{T,X,W,<:Any,FEM3D{T}}, ts::AbstractVector, U::Matrix{T};
297297
frame_time::Real = max(0.001, minimum(diff(ts))),
298298
kwargs...) where {T,X,W}
299299

@@ -390,7 +390,7 @@ Plot an animated 3D visualization of a parabolic solution (FEM3D).
390390
# Returns
391391
- `HTML5anim`: An HTML5 video that displays in Jupyter notebooks.
392392
"""
393-
function plot(sol::ParabolicSOL{T,X,W,<:Any,<:Geometry{T,<:Any,<:Any,<:Any,<:Any,FEM3D{T}}}, k::Int=1; kwargs...) where {T,X,W}
393+
function plot(sol::ParabolicSOL{T,X,W,<:Any,<:Geometry{T,<:Any,<:Any,<:Any,FEM3D{T}}}, k::Int=1; kwargs...) where {T,X,W}
394394
return plot(sol.geometry, collect(sol.ts), hcat([sol.u[j][:, k] for j=1:length(sol.ts)]...); kwargs...)
395395
end
396396

src/Parabolic.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct ParabolicSOL{T,X,W,Discretization,G}
4949
ts::Vector{T}
5050
u::Vector{X}
5151
end
52-
function ParabolicSOL(geometry::Geometry{T,<:Any,W,<:Any,<:Any,Discretization}, ts, u::Vector{X}) where {T,X,W,Discretization}
52+
function ParabolicSOL(geometry::Geometry{T,<:Any,W,<:Any,Discretization}, ts, u::Vector{X}) where {T,X,W,Discretization}
5353
ParabolicSOL{T,X,W,Discretization,typeof(geometry)}(geometry, collect(T, ts), u)
5454
end
5555

@@ -75,7 +75,7 @@ function Base.show(io::IO, ::MIME"text/html", A::HTML5anim)
7575
print(io, A.anim)
7676
end
7777

78-
function plot(M::Geometry{T,X,W,<:Any,<:Any,Discretization}, ts::AbstractVector{T}, U::AbstractMatrix{T};
78+
function plot(M::Geometry{T,X,W,<:Any,Discretization}, ts::AbstractVector{T}, U::AbstractMatrix{T};
7979
frame_time::Real = max(0.001, minimum(diff(ts))),
8080
embed_limit=200.0,
8181
printer=(animation)->nothing

0 commit comments

Comments
 (0)