-
Notifications
You must be signed in to change notification settings - Fork 238
Adds grid metrics to NetCDF output #2652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
20216ab
da09453
a8d70da
ec36123
db58ac8
ebacc69
a6203b6
30f467f
ec1e035
b8b8059
14b0e2c
021e8a8
7d9d1a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -468,6 +468,34 @@ julia> minimum_zspacing(grid, Center(), Center(), Center()) | |
minimum_zspacing(grid, ℓx, ℓy, ℓz) = minimum_spacing(:z, grid, ℓx, ℓy, ℓz) | ||
minimum_zspacing(grid) = minimum_spacing(:z, grid, Center(), Center(), Center()) | ||
|
||
flip_loc(::Center) = Face() | ||
flip_loc(::Face) = Center() | ||
|
||
active_xspacing_at_boundary(i,j,k,grid, ℓx, ℓy, ℓz) = ifelse(i==1, xnode(i,j,k, grid, flip_loc(ℓx), ℓy, ℓz) - xnode(i,j,k, grid, ℓx, ℓy, ℓz), | ||
xnode(i,j,k, grid, ℓx, ℓy, ℓz) - xnode(i-1,j,k, grid, flip_loc(ℓx), ℓy, ℓz)) | ||
|
||
active_yspacing_at_boundary(i,j,k,grid, ℓx, ℓy, ℓz) = ifelse(j==1, ynode(i,j,k, grid, ℓx, flip_loc(ℓy), ℓz) - ynode(i,j,k, grid, ℓx, ℓy, ℓz), | ||
ynode(i,j,k, grid, ℓx, ℓy, ℓz) - ynode(i,j-1,k, grid, ℓx, flip_loc(ℓy), ℓz)) | ||
|
||
active_zspacing_at_boundary(i,j,k,grid, ℓx, ℓy, ℓz) = ifelse(k==1, znode(i,j,k, grid, ℓx, ℓy, flip_loc(ℓz)) - znode(i,j,k, grid, ℓx, ℓy, ℓz), | ||
znode(i,j,k, grid, ℓx, ℓy, ℓz) - znode(i,j,k-1, grid, ℓx, ℓy, flip_loc(ℓz))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do these do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These implement the behavior defined here. I'm not sure if that's a good name for that function, but whatever we call it, I'm going to make sure it has a helpful docstring before we merge (if in fact that function survives). This I believe (I'm confirming it here) is the proper way to define spacings in a staggered grid following SGRID conventions. |
||
for dir in (:x, :y, :z) | ||
active_spacing = Symbol(:active_, dir, :spacing) | ||
spacing = Symbol(dir, :spacing) | ||
boundary_spacing = Symbol(active_spacing, :_at_boundary) | ||
@eval begin | ||
function $active_spacing(i, j, k, grid, ℓx, ℓy, ℓz) | ||
Δξ = ifelse(inactive_node(i, j, k, grid, ℓx, ℓy, ℓz), | ||
0, | ||
ifelse(boundary_node(i, j, k, grid, ℓx, ℓy, ℓz), | ||
$boundary_spacing(i, j, k, grid, ℓx, ℓy, ℓz), | ||
$spacing(i, j, k, grid, ℓx, ℓy, ℓz))) | ||
return Δξ | ||
end | ||
end | ||
end | ||
|
||
|
||
##### | ||
##### Convenience functions | ||
##### | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
using Oceananigans.Grids: active_xspacing, active_yspacing, active_zspacing | ||
|
||
|
||
import Oceananigans.OutputWriters: save_output!, define_output_variable! | ||
using Oceananigans.OutputWriters: fetch_and_convert_output, drop_output_dims, | ||
netcdf_spatial_dimensions, output_indices | ||
using Oceananigans.Fields: AbstractField | ||
using NCDatasets: defVar | ||
|
||
define_timeconstant_variable!(dataset, output::AbstractField, name, array_type, compression, output_attributes, dimensions) = | ||
defVar(dataset, name, eltype(array_type), netcdf_spatial_dimensions(output), | ||
compression=compression, attrib=output_attributes) | ||
|
||
function save_output!(ds, output, model, ow, name) | ||
|
||
data = fetch_and_convert_output(output, model, ow) | ||
data = drop_output_dims(output, data) | ||
colons = Tuple(Colon() for _ in 1:ndims(data)) | ||
ds[name][colons...] = data | ||
return nothing | ||
end | ||
|
||
function grid_metric_locations(outputs) | ||
location_list = [] | ||
for output in values(outputs) | ||
loc = location(output) | ||
if (loc ∉ location_list) && (Nothing ∉ loc) | ||
push!(location_list, location(output)) | ||
end | ||
end | ||
return location_list | ||
end | ||
|
||
loc_superscript(::Type{Center}) = "ᶜ" | ||
loc_superscript(::Type{Face}) = "ᶠ" | ||
loc_superscript(::Type{Nothing}) = "ⁿ" | ||
function default_grid_spacings(outputs, grid::AbstractRectilinearGrid) | ||
loc_list = unique(map(location, values(outputs))) | ||
spacing_operations = Dict() | ||
|
||
for loc in loc_list | ||
LX, LY, LZ = loc | ||
|
||
# Let's replace Nothing for Center for now since `active_xyzspacing` doesn't accept Nothing as location | ||
LX = LX == Nothing ? Center : LX | ||
LY = LY == Nothing ? Center : LY | ||
LZ = LZ == Nothing ? Center : LZ | ||
|
||
Δx_name = "Δx" * loc_superscript(LX) * "ᵃᵃ" | ||
Δy_name = "Δyᵃ" * loc_superscript(LY) * "ᵃ" | ||
Δz_name = "Δzᵃᵃ" * loc_superscript(LZ) | ||
|
||
push!(spacing_operations, | ||
Δx_name => Average(KernelFunctionOperation{LX, LY, LZ}(active_xspacing, grid, LX(), LY(), LZ()), dims=(2,3)), | ||
Δy_name => Average(KernelFunctionOperation{LX, LY, LZ}(active_yspacing, grid, LX(), LY(), LZ()), dims=(1,3)), | ||
Δz_name => Average(KernelFunctionOperation{LX, LY, LZ}(active_zspacing, grid, LX(), LY(), LZ()), dims=(1,2))) | ||
end | ||
return Dict(name => Field(op) for (name, op) in spacing_operations) | ||
end | ||
|
||
function write_grid_metrics!(ow, metrics; user_indices = (:, :, :), with_halos=false) | ||
ds = open(ow) | ||
@show keys(ds) | ||
|
||
for (metric_name, metric_operation) in metrics | ||
indices = output_indices(metric_operation, metric_operation.grid, user_indices, with_halos) | ||
sliced_metric = Field(metric_operation, indices=indices) | ||
|
||
@show metric_name | ||
define_timeconstant_variable!(ds, sliced_metric, metric_name, ow.array_type, 0, Dict(), ("xC", "yC", "zC")) | ||
save_output!(ds, sliced_metric, model, ow, metric_name) | ||
end | ||
close(ds) | ||
end | ||
|
||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.