Skip to content

Commit 8cc95ba

Browse files
committed
WIP new smart coarsening with Graphs.jl: Don't lump disconnected cells!
1 parent c5fe6bd commit 8cc95ba

6 files changed

Lines changed: 95 additions & 13 deletions

File tree

Project.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
name = "OceanTransportMatrixBuilder"
22
uuid = "c2b4a04e-6049-4fc4-aa6a-5508a29a1e1c"
3+
version = "0.8.0"
34
authors = ["Benoit Pasquier <briochemc@gmail.com> and contributors"]
4-
version = "0.7.2"
55

66
[deps]
77
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
8+
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
89
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
910
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1011
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1112

1213
[compat]
1314
Distances = "0.10"
15+
Graphs = "1.13.1"
1416
LinearAlgebra = "1"
1517
SparseArrays = "1"
1618
StaticArrays = "1"
1719
julia = "1.10"
1820

1921
[extras]
20-
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
2122
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
23+
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
2224
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
2325
DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0"
2426
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
@@ -35,4 +37,4 @@ YAXArrays = "c21b50f5-aa40-41ea-b809-c0f5e47bfa5c"
3537
Zarr = "0a941bbe-ad1d-11e8-39d9-ab76183a1d99"
3638

3739
[targets]
38-
test = ["CairoMakie", "CSV", "DataFrames", "DimensionalData", "Downloads", "GibbsSeaWater", "LinearAlgebra", "Makie", "NaNStatistics", "NetCDF", "Test", "TestItemRunner", "TestItems", "Unitful", "YAXArrays", "Zarr"]
40+
test = ["CairoMakie", "CSV", "DataFrames", "DimensionalData", "Downloads", "GibbsSeaWater", "LinearAlgebra", "Makie", "NaNStatistics", "NetCDF", "Test", "TestItemRunner", "TestItems", "Unitful", "YAXArrays", "Zarr"]

src/OceanTransportMatrixBuilder.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ using LinearAlgebra
77
# deps
88
using Distances: haversine
99
using StaticArrays: FieldVector
10+
using Graphs: SimpleGraph, connected_components
1011

1112
# Main functions to be exposed
1213
include("matrixbuilding.jl")

src/extratools.jl

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,56 @@ where the lumping should occur.
3131
Outside of this region, no lumping.
3232
Default is `f=Returns(true)`, i.e. lump everywhere.
3333
"""
34-
function lump_and_spray(wet3D, vol, mask=trues(size(wet3D)); di=2, dj=2, dk=1)
34+
function lump_and_spray(wet3D, vol, T, mask=trues(size(wet3D)); di=2, dj=2, dk=1)
3535

3636
# extend the grid to avoid lumping cells outside of bounds
3737
nxyz = size(wet3D)
3838
C = CartesianIndices(nxyz)
3939
LUMPidx = zeros(Int, nxyz .+ (di - 1, dj - 1, dk - 1))
4040

41+
wet = wet3D[:]
42+
i, j = findnz(T)
43+
L = LinearIndices(nxyz .+ (di - 1, dj - 1, dk - 1))
44+
wet3Dext = falses(nxyz .+ (di - 1, dj - 1, dk - 1))
45+
wet3Dext[C[wet3D]] .= true
46+
Lwet = L[wet3Dext] # careful here, as L is larger than wet3D
47+
48+
connectivitymatrix = sparse(Lwet[i], Lwet[j], true, length(LUMPidx), length(LUMPidx))
49+
4150
# loop once over all grid cells and assign lumped indices
42-
c = 1 # index / counter
51+
c = 2 # index / counter (we start at 2 because 1 is reserved for dry cells)
4352
neighbours = CartesianIndices((0:di-1, 0:dj-1, 0:dk-1))
4453
for 𝑖 in eachindex(C)
4554
C𝑖 = C[𝑖]
46-
LUMPidx[C𝑖] 0 && mask[C𝑖] && continue # skip if index already assigned
55+
# skip if index already assigned and in mask
56+
#(if assigned but not in mask, must reassign)
57+
LUMPidx[C𝑖] > 0 && mask[C𝑖] && continue
4758
if mask[C𝑖] # if in region, assign all neighbours also in region
48-
LUMPidx[C𝑖 .+ neighbours] .= c
49-
else # to only this cell if outside region
59+
# list of neighbours
60+
L𝑖 = L[C𝑖 .+ neighbours][:]
61+
# First, assign dry index to dry cells
62+
localwet = wet3Dext[L𝑖]
63+
dryidx = L𝑖[.!localwet]
64+
LUMPidx[dryidx] .= 1
65+
# Then build a simple connectivity graph of the remaining cells to be lumped
66+
wetidx = L𝑖[localwet]
67+
localconnectivitymatrix = view(connectivitymatrix, wetidx, wetidx)
68+
g = SimpleGraph(localconnectivitymatrix)
69+
# and split it in connected components
70+
for comp in connected_components(g)
71+
LUMPidx[wetidx[comp]] .= c
72+
c += 1
73+
end
74+
else # if outside region, assign new index
5075
LUMPidx[C𝑖] = c
76+
c += 1
5177
end
52-
c += 1
5378
end
5479

5580
# Remove ghost cells outside of original grid
5681
LUMP = sparse(LUMPidx[C][:], 1:length(C), 1)
5782

5883
# Find wet points in coarsened grid
59-
wet = wet3D[:]
6084
wet_c = LUMP * wet .> 0
6185

6286
# Extract only indices of wet grd points
@@ -84,6 +108,18 @@ function lump_and_spray(wet3D, vol, mask=trues(size(wet3D)); di=2, dj=2, dk=1)
84108
end
85109

86110

111+
"""
112+
diconnected_cells(wet3D, T; di=2, dj=2, dk=1)
113+
114+
"""
115+
function connected_cells(wet3D, T; di=2, dj=2, dk=1)
116+
i, j = findnz(SPRAY * LUMP)
117+
connected_by_grid = sparse(i, j, true, size(T)...)
118+
i, j = findnz(T)
119+
connected_by_T = sparse(i, j, true, size(T)...)
120+
connected = connected_by_grid .& connected_by_T
121+
connected = ((connected^di)^dj)^dk
122+
end
87123

88124

89125

test/interactive.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,31 @@ end
120120

121121
# @profview transportmatrix(; ϕ, mlotst, gridmetrics, indices, ρ, κH, κVML, κVdeep)
122122
# @profview_allocs transportmatrix(; ϕ, mlotst, gridmetrics, indices, ρ, κH, κVML, κVdeep) sample_rate=0.9
123+
124+
125+
# unpack model grid
126+
(; v3D, lat, lon, zt) = gridmetrics
127+
# unpack indices
128+
(; wet3D, N) = indices
129+
130+
v = v3D[wet3D]
131+
132+
@info "coarsening grid"
133+
SOmask = lat .< -35
134+
NAmask = @. (lat > 50) & ((lon < 100) | (250 < lon))
135+
mymask = repeat(.!SOmask .& .!NAmask, 1, 1, size(wet3D, 3))
136+
137+
# Test extreme coarsening and plot it
138+
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, T, mymask; di=10, dj=10, dk=1)
139+
# Plot the lumping
140+
using CairoMakie
141+
sprayedrand = SPRAY * rand(size(LUMP, 1))
142+
sprayedrand3D = OceanTransportMatrixBuilder.as3D(sprayedrand, wet3D)
143+
fig, ax, hm = surface(mod.(lon .- 80, 360) .+ 80, lat, zeros(size(lat));
144+
color=sprayedrand3D[:,:,45],
145+
colormap = :turbo,
146+
shading = false
147+
)
148+
outputfile = joinpath(outputdir, "LUMP_and_SPRAY_coarsening.png")
149+
@info "Saving coarsening as image file:\n $(joinpath("test", outputfile))"
150+
save(outputfile, fig)

test/local_full.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ end
119119
using Unitful: s, yr
120120
using NaNStatistics
121121
using CairoMakie
122+
using Graphs
122123

123124
(; gridmetrics, indices, T, model, member, outputdir) = LocalBuiltMatrix
124125

@@ -133,8 +134,22 @@ end
133134
SOmask = lat .< -35
134135
NAmask = @. (lat > 50) & ((lon < 100) | (250 < lon))
135136
mymask = repeat(.!SOmask .& .!NAmask, 1, 1, size(wet3D, 3))
136-
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, mymask; di=2, dj=2, dk=1)
137-
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v; di=2, dj=2, dk=1)
137+
138+
# Test extreme coarsening to show behavior across land and plot it
139+
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, T, mymask; di=10, dj=10, dk=1)
140+
sprayedrand = SPRAY * rand(size(LUMP, 1))
141+
sprayedrand3D = OceanTransportMatrixBuilder.as3D(sprayedrand, wet3D)
142+
fig, ax, hm = surface(mod.(lon .- 80, 360) .+ 80, lat, zeros(size(lat));
143+
color=sprayedrand3D[:,:,1],
144+
colormap = :turbo,
145+
shading = false
146+
)
147+
outputfile = joinpath(outputdir, "LUMP_and_SPRAY_coarsening.png")
148+
@info "Saving coarsening as image file:\n $(joinpath("test", outputfile))"
149+
save(outputfile, fig)
150+
151+
# Redo coarsening with less extreme coarsening
152+
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, T; di=2, dj=2, dk=1)
138153

139154
# surface mask
140155
issrf3D = copy(wet3D)

test/online.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,6 @@
128128
SOmask = lat .< -35
129129
NAmask = @. (lat > 50) & ((lon < 100) | (250 < lon))
130130
mymask = repeat(.!SOmask .& .!NAmask, 1, 1, size(wet3D, 3))
131-
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, mymask; di=2, dj=2, dk=1)
131+
LUMP, SPRAY, v_c = OceanTransportMatrixBuilder.lump_and_spray(wet3D, v, T, mymask; di=2, dj=2, dk=1)
132132

133133
end

0 commit comments

Comments
 (0)