Skip to content

Commit 3cd1645

Browse files
authored
(0.100.5) Fix outputting index-reduced fields like the free surface height (#4567)
1 parent b49a1b6 commit 3cd1645

File tree

4 files changed

+57
-21
lines changed

4 files changed

+57
-21
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Oceananigans"
22
uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09"
33
authors = ["Climate Modeling Alliance and contributors"]
4-
version = "0.100.4"
4+
version = "0.100.5"
55

66
[deps]
77
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

ext/OceananigansNCDatasetsExt.jl

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using Oceananigans.Architectures: CPU, GPU, on_architecture
1212
using Oceananigans.AbstractOperations: KernelFunctionOperation, AbstractOperation
1313
using Oceananigans.BuoyancyFormulations: BuoyancyForce, BuoyancyTracer, SeawaterBuoyancy, LinearEquationOfState
1414
using Oceananigans.Fields
15-
using Oceananigans.Fields: Reduction, reduced_dimensions, reduced_location, location
15+
using Oceananigans.Fields: Reduction, reduced_dimensions, reduced_location, location, indices
1616
using Oceananigans.Grids: Center, Face, Flat, Periodic, Bounded,
1717
AbstractGrid, RectilinearGrid, LatitudeLongitudeGrid, StaticVerticalDiscretization,
1818
topology, halo_size, xspacings, yspacings, zspacings, λspacings, φspacings,
@@ -88,7 +88,7 @@ already exist, they are validated to match the expected dimensions for the given
8888
8989
Arguments:
9090
- `ds`: NetCDF dataset
91-
- `field`: AbstractField being written
91+
- `field`: AbstractField being written
9292
- `all_dims`: Tuple of dimension names to create/validate
9393
- `dimension_name_generator`: Function to generate dimension names
9494
"""
@@ -103,7 +103,7 @@ function create_field_dimensions!(ds, field::AbstractField, all_dims, dimension_
103103
if "time" in all_dims && "time" keys(ds.dim)
104104
create_time_dimension!(ds)
105105
end
106-
106+
107107
return nothing
108108
end
109109

@@ -162,6 +162,34 @@ function create_spatial_dimensions!(dataset, dims, attributes_dict; array_type=A
162162
end
163163
end
164164

165+
"""
166+
effective_reduced_dimensions(field)
167+
168+
Return dimensions that are effectively reduced, considering both location-based reduction
169+
(e.g. a `Nothing` location) and index-based reduction at boundaries (e.g. free surface
170+
height fields with :, :, Nz+1:Nz+1 indices).
171+
```
172+
"""
173+
function effective_reduced_dimensions(field)
174+
loc_reduced = reduced_dimensions(field)
175+
176+
idx_reduced = ()
177+
inds = indices(field)
178+
grid_size = size(field.grid)
179+
180+
for (dim, ind) in enumerate(inds)
181+
if ind isa UnitRange && length(ind) == 1
182+
index_value = first(ind)
183+
if index_value > grid_size[dim]
184+
idx_reduced = (idx_reduced..., dim)
185+
end
186+
end
187+
end
188+
189+
all_reduced = (loc_reduced..., idx_reduced...)
190+
return Tuple(unique(all_reduced))
191+
end
192+
165193
#####
166194
##### Gathering of grid dimensions
167195
#####
@@ -429,10 +457,13 @@ end
429457

430458
function field_dimensions(field::AbstractField, grid::RectilinearGrid, dim_name_generator)
431459
LX, LY, LZ = location(field)
460+
TX, TY, TZ = topology(grid)
461+
462+
eff_reduced_dims = effective_reduced_dimensions(field)
432463

433-
x_dim_name = dim_name_generator("x", grid, LX(), nothing, nothing, Val(:x))
434-
y_dim_name = dim_name_generator("y", grid, nothing, LY(), nothing, Val(:y))
435-
z_dim_name = dim_name_generator("z", grid, nothing, nothing, LZ(), Val(:z))
464+
x_dim_name = (1 eff_reduced_dims || TX == Flat) ? "" : dim_name_generator("x", grid, LX(), nothing, nothing, Val(:x))
465+
y_dim_name = (2 eff_reduced_dims || TY == Flat) ? "" : dim_name_generator("y", grid, nothing, LY(), nothing, Val(:y))
466+
z_dim_name = (3 eff_reduced_dims || TZ == Flat) ? "" : dim_name_generator("z", grid, nothing, nothing, LZ(), Val(:z))
436467

437468
x_dim_name = isempty(x_dim_name) ? tuple() : tuple(x_dim_name)
438469
y_dim_name = isempty(y_dim_name) ? tuple() : tuple(y_dim_name)
@@ -443,10 +474,13 @@ end
443474

444475
function field_dimensions(field::AbstractField, grid::LatitudeLongitudeGrid, dim_name_generator)
445476
LΛ, LΦ, LZ = location(field)
477+
TΛ, TΦ, TZ = topology(grid)
478+
479+
eff_reduced_dims = effective_reduced_dimensions(field)
446480

447-
λ_dim_name = dim_name_generator("λ", grid, (), nothing, nothing, Val(:x))
448-
φ_dim_name = dim_name_generator("φ", grid, nothing, (), nothing, Val(:y))
449-
z_dim_name = dim_name_generator("z", grid, nothing, nothing, LZ(), Val(:z))
481+
λ_dim_name = (1 eff_reduced_dims ||== Flat) ? "" : dim_name_generator("λ", grid, (), nothing, nothing, Val(:x))
482+
φ_dim_name = (2 eff_reduced_dims ||== Flat) ? "" : dim_name_generator("φ", grid, nothing, (), nothing, Val(:y))
483+
z_dim_name = (3 eff_reduced_dims || TZ == Flat) ? "" : dim_name_generator("z", grid, nothing, nothing, LZ(), Val(:z))
450484

451485
λ_dim_name = isempty(λ_dim_name) ? tuple() : tuple(λ_dim_name)
452486
φ_dim_name = isempty(φ_dim_name) ? tuple() : tuple(φ_dim_name)
@@ -1403,11 +1437,15 @@ drop_output_dims(output, data) = data # fallback
14031437
drop_output_dims(output::WindowedTimeAverage{<:Field}, data) = drop_output_dims(output.operand, data)
14041438

14051439
function drop_output_dims(field::Field, data)
1406-
reduced_dims = reduced_dimensions(field)
1440+
eff_reduced_dims = effective_reduced_dimensions(field)
14071441
flat_dims = Tuple(i for (i, T) in enumerate(topology(field.grid)) if T == Flat)
1408-
dims = (reduced_dims..., flat_dims...)
1442+
dims = (eff_reduced_dims..., flat_dims...)
14091443
dims = Tuple(Set(dims)) # ensure dims are unique
1410-
return dropdims(data; dims)
1444+
1445+
# Only drop dimensions that exist in the data and are size 1
1446+
dims = filter(d -> d <= ndims(data) && size(data, d) == 1, dims)
1447+
1448+
return isempty(dims) ? data : dropdims(data; dims=tuple(dims...))
14111449
end
14121450

14131451
#####

test/test_jld2_writer.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ function test_jld2_time_averaging_of_horizontal_averages(model)
166166
test_file_name = "jld2_time_averaging_test.jld2"
167167
file = jldopen(test_file_name)
168168

169-
# Data is saved without halos
170-
wu = file["timeseries/wu/4"][1, 1, 3]
171-
uv = file["timeseries/uv/4"][1, 1, 3]
172-
wT = file["timeseries/wT/4"][1, 1, 3]
169+
# Data is saved without halos, and with singleton dimensions dropped
170+
wu = file["timeseries/wu/4"][3]
171+
uv = file["timeseries/uv/4"][3]
172+
wT = file["timeseries/wT/4"][3]
173173

174174
close(file)
175175

test/test_netcdf_writer.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,9 +2550,8 @@ function test_netcdf_free_surface_only_output(arch)
25502550
Nt = 5
25512551
simulation = Simulation(model, Δt=0.1, stop_iteration=Nt)
25522552

2553-
# Kind of a hack because we want η to be a ReducedField.
25542553
outputs = (;
2555-
η = Average(model.free_surface.η, dims=3),
2554+
η = model.free_surface.η,
25562555
)
25572556

25582557
Arch = typeof(arch)
@@ -2617,9 +2616,8 @@ function test_netcdf_free_surface_mixed_output(arch)
26172616
Nt = 5
26182617
simulation = Simulation(model, Δt=0.1, stop_iteration=Nt)
26192618

2620-
# Kind of a hack because we want η to be a ReducedField.
26212619
free_surface_outputs = (;
2622-
η = Average(model.free_surface.η, dims=3),
2620+
η = model.free_surface.η,
26232621
)
26242622

26252623
outputs = merge(model.velocities, model.tracers, free_surface_outputs)

0 commit comments

Comments
 (0)