Skip to content

Commit f2c91ee

Browse files
Add support for temporary mask-aware reductions (#2286)
1 parent bc75cda commit f2c91ee

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

docs/src/masks.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,60 @@ operations of mask-aware and mask-unaware:
169169
This was a design implementation detail, users should not generally depend on the results where `mask == 0`, in case this is changed in the future.
170170
- internal array operations (`fill!(parent(field), 0)`) mask-unaware.
171171

172+
## Temporary work-arounds
173+
174+
We can perform mask-aware reductions with the following work-around
175+
176+
```julia
177+
using ClimaComms
178+
ClimaComms.@import_required_backends
179+
import ClimaCore: Spaces, Fields, DataLayouts, Geometry, Operators
180+
using ClimaCore.CommonSpaces
181+
using Test
182+
183+
FT = Float64
184+
ᶜspace = ExtrudedCubedSphereSpace(FT;
185+
z_elem = 10,
186+
z_min = 0,
187+
z_max = 1,
188+
radius = 10,
189+
h_elem = 10,
190+
n_quad_points = 4,
191+
staggering = CellCenter(),
192+
enable_mask = true,
193+
)
194+
ᶠspace = Spaces.face_space(ᶜspace)
195+
ᶠcoords = Fields.coordinate_field(ᶠspace)
196+
197+
# Set the mask
198+
Spaces.set_mask!(ᶜspace) do coords
199+
coords.lat > 0.5
200+
end
201+
202+
# get the mask
203+
mask = Spaces.get_mask(ᶜspace)
204+
205+
# make a field of ones
206+
ᶜf = ones(ᶜspace) # ignores mask
207+
208+
# bitmask spanning datalayout
209+
bm = DataLayouts.full_bitmask(mask, Fields.field_values(ᶜf));
210+
211+
# mask-unaware integral (includes jacobian weighting)
212+
@show sum(ᶜf)
213+
214+
# mask-unaware sum (excludes jacobian weighting)
215+
@show sum(Fields.field_values(ᶜf))
216+
217+
# mask-aware sum (excludes jacobian)
218+
@show sum(parent(ᶜf)[bm])
219+
220+
# level mask
221+
ᶜf_lev = Fields.level(ᶜf, 1);
222+
bm_lev = DataLayouts.full_bitmask(mask, Fields.field_values(ᶜf_lev));
223+
@show sum(parent(ᶜf_lev)[bm_lev])
224+
```
225+
172226
## Developer docs
173227

174228
In order to support masks, we define their types in `DataLayouts`, since

src/DataLayouts/DataLayouts.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,4 +2352,33 @@ function IJHMask(is_active::Union{IJFH, IJHF})
23522352
)
23532353
end
23542354

2355+
"""
2356+
full_bitmask(mask::IJHMask, data::AbstractData)
2357+
2358+
Returns an array similar to `parent(data)`, containing
2359+
bools indicating when the `mask`'s `is_active == true`.
2360+
2361+
!!! warn
2362+
2363+
This function provides users a work-around to compute mask-aware reductions,
2364+
and should be deprecated in favor of providing native masked-reduction
2365+
support. Therefore, this function should be used sparingly.
2366+
2367+
This feature is extensible, but not performant in that it allocates
2368+
and, on the gpu, will launch many kernels.
2369+
"""
2370+
function full_bitmask end
2371+
2372+
full_bitmask(mask::AbstractMask, data::AbstractData; complement::Bool = false) =
2373+
full_bitmask(mask, nlevels(data), singleton(data); complement)
2374+
2375+
function full_bitmask(mask::IJHMask, Nv, s::VIJFHSingleton; complement::Bool)
2376+
_arr = parent(mask.is_active)
2377+
arr = complement ? .!_arr : _arr
2378+
return repeat(reshape(arr, 1, size(arr)...), Nv)
2379+
end
2380+
2381+
full_bitmask(mask::AbstractMask, data::IJFH; complement::Bool = false) =
2382+
complement ? .!parent(mask.is_active) : parent(mask.is_active)
2383+
23552384
end # module

0 commit comments

Comments
 (0)