11"""
2- LUMP, SPRAY = lump_and_spray(wet3D, volume; di=2, dj=2, dk=1)
2+ LUMP, SPRAY, v_c = lump_and_spray(wet3D, volume; f=Returns(true), di=2, dj=2, dk=1)
33
4- returns the LUMP and SPRAY matrices that go with the
5- coarsened grid (also returned).
4+ returns the LUMP and SPRAY matrices, and the coarsened volume vector.
65
76To get the coarsened vector from fine vector x, use
87
@@ -23,58 +22,43 @@ will lump:
2322- every 4 cells in the y direction (lat),
2423- and every 1 cell (default) in the z direction (depth).
2524
26- Expected grid arrangement is OCIM2 like, i.e.,
27- lat × lon × depth.
25+ The optional function argument `f` can be used to specify a region
26+ where the lumping should occur.
27+ `f` should be a function of the indices, e.g.,
2828
29- You can also provide a vector of indices instead of a scalar
30- in order to customize the coarsening. For example,
29+ f(i,j,k) = lat[i,j] > -40 # only lump north of 40°S
3130
32- lump_and_spray(wet3D, volume; di=[1 1 1 1 1 1 1 2 2 2 ... n])
33-
34- will lump all the boxes in the x dimension that are marked
35- with a 1, then all those marked with a 2, and so on.
36- Confusing? Let me give a practical example. Say you want to
37- coarsen the ACCESS grid in the vertical to match the OCIM grid.
38- The you can do
39-
40- [~, zidx] = min(abs(ACCESSgrd.zt - OCIMgrd.zt'), [], 1)
41-
42- to get the OCIM2 z-indices that are closest to the
43- ACCESS z-indices. And then you can pass it to this function via
44-
45- lump_and_spray(wet3D, volume; dk=zidx)
46-
47- TODO: Fix these docs that have not been fully translated from MATLAB version.
31+ Outside of this region, no lumping.
32+ Default is `f=Returns(true)`, i.e. lump everywhere.
4833"""
49- lump_and_spray (wet3D, volume; di= 2 , dj= 2 , dk= 1 ) = _lump_and_spray (wet3D, volume, di, dj, dk)
50- function _lump_and_spray (wet3D, volume, di:: Int , dj:: Int , dk:: Int )
51- # grd wet array and vector and sizes
52- nx, ny, nz = size (wet3D)
53- # Convert scalar lumping options into lumping indices vector
54- # So that syntax like `di=2` works
55- vi = repeat (1 : nx, inner= di)[1 : nx]
56- vj = repeat (1 : ny, inner= dj)[1 : ny]
57- vk = repeat (1 : nz, inner= dk)[1 : nz]
58-
59- return _lump_and_spray (wet3D, volume, vi, vj, vk)
60- end
61- function _lump_and_spray (wet3D, volume, vi, vj, vk)
62- wet = wet3D[:]
63- nx, ny, nz = size (wet3D)
64- # Create lumping matrices in each dimension
65- LUMPx = sparse (vi, 1 : nx, true )
66- LUMPy = sparse (vj, 1 : ny, true )
67- LUMPz = sparse (vk, 1 : nz, true )
68- # kron each dimension to build whole LUMP matrix
69- LUMP = kron (LUMPz, kron (LUMPy, LUMPx))
34+ function lump_and_spray (wet3D, volume; f= Returns (true ), di= 2 , dj= 2 , dk= 1 )
35+
36+ # extend the grid to avoid lumping cells outside of bounds
37+ nxyz = size (wet3D)
38+ LUMPidx = zeros (Int, nxyz .+ (di - 1 , dj - 1 , dk - 1 ))
39+
40+ # loop once over all grid cells and assign lumped indices
41+ c = 1 # index / counter
42+ neighbours = CartesianIndices ((0 : di- 1 , 0 : dj- 1 , 0 : dk- 1 ))
43+ C = CartesianIndices (nxyz)
44+ for 𝑖 in eachindex (C)
45+ C𝑖 = C[𝑖]
46+ i, j, k = C𝑖. I
47+ # assign index if not indexed yet
48+ if LUMPidx[C𝑖] == 0
49+ if f (i,j,k) # to all lumped cells if in region
50+ LUMPidx[C𝑖 .+ neighbours] .= c
51+ else # to only this cell if outside region
52+ LUMPidx[C𝑖] = c
53+ end
54+ c += 1
55+ end
56+ end
57+ LUMP = sparse (LUMPidx[:], 1 : length (LUMPidx), 1 )
7058
7159 # Find wet points in coarsened grid
60+ wet = wet3D[:]
7261 wet_c = LUMP * wet .> 0
73- nx_c = vi[end ]
74- ny_c = vj[end ]
75- nz_c = vk[end ]
76- wet3D_c = fill (false , nx_c, ny_c, nz_c)
77- wet3D_c[wet_c] .= true
7862
7963 # Extract only indices of wet grd points
8064 LUMP = LUMP[wet_c, wet]
@@ -90,17 +74,13 @@ function _lump_and_spray(wet3D, volume, vi, vj, vk)
9074 SPRAY = copy (LUMP' )
9175 SPRAY. nzval .= 1
9276
93- return LUMP, SPRAY, wet3D_c, volume_c
77+ return LUMP, SPRAY, volume_c
9478end
9579
9680
9781
9882
9983
100-
101-
102-
103-
10484"""
10585as2D(x, wet3D)
10686
0 commit comments