Skip to content

Commit 2df2cd2

Browse files
glwagnernavidcy
andauthored
Add download_bathymetry (#391)
* glw-nc/download-bathymetry * add docstring * Only download on root * fix typo * import @root * fix using @root * try without @root * Apply suggestions from code review * add @root back let's see if distributed tests were failing with root for some random unrelated reason * Update Bathymetry.jl --------- Co-authored-by: Navid C. Constantinou <[email protected]>
1 parent 1a05bfe commit 2df2cd2

File tree

1 file changed

+44
-27
lines changed

1 file changed

+44
-27
lines changed

src/Bathymetry.jl

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
module Bathymetry
22

3-
export regrid_bathymetry, retrieve_bathymetry
3+
export regrid_bathymetry, retrieve_bathymetry, download_bathymetry
44

55
using ImageMorphology
66
using ..DataWrangling: download_progress
7+
using ..DistributedUtils: @root
78

89
using Oceananigans
910
using Oceananigans.Architectures: architecture, on_architecture
@@ -36,6 +37,28 @@ end
3637
etopo_url = "https://www.dropbox.com/scl/fi/6pwalcuuzgtpanysn4h6f/" *
3738
"ETOPO_2022_v1_60s_N90W180_surface.nc?rlkey=2t7890ruyk4nd5t5eov5768lt&st=yfxsy1lu&dl=0"
3839

40+
"""
41+
download_bathymetry(; dir = download_bathymetry_cache,
42+
url = etopo_url,
43+
filename = "ETOPO_2022_v1_60s_N90W180_surface.nc")
44+
45+
Download the bathymetry from `url` and saves it under `filename` in the directory `dir` and
46+
return the full filepath where the bathymetry is saved.
47+
"""
48+
function download_bathymetry(; url = etopo_url,
49+
dir = download_bathymetry_cache,
50+
filename = "ETOPO_2022_v1_60s_N90W180_surface.nc")
51+
52+
filepath = joinpath(dir, filename)
53+
54+
#TODO: embed this into a @root macro; see failed attempts in https://github.com/CliMA/ClimaOcean.jl/pull/391
55+
if !isfile(filepath)
56+
Downloads.download(url, filepath; progress=download_progress)
57+
end
58+
59+
return filepath
60+
end
61+
3962
"""
4063
regrid_bathymetry(target_grid;
4164
height_above_water = nothing,
@@ -57,10 +80,10 @@ Arguments
5780
Keyword Arguments
5881
=================
5982
60-
- `height_above_water`: limits the maximum height of above-water topography (where ``h > 0``) before inetrpolating.
83+
- `height_above_water`: limits the maximum height of above-water topography (where ``h > 0``) before interpolating.
6184
Default: `nothing`, which implies that the original topography is retained.
6285
63-
- `minimum_depth`: minimum depth for the shallow regions, defined as a positive value.
86+
- `minimum_depth`: minimum depth for the shallow regions, defined as a positive value.
6487
`h > - minimum_depth` is considered land. Default: 0.
6588
6689
- `dir`: directory of the bathymetry-containing file. Default: `download_bathymetry_cache`.
@@ -103,13 +126,7 @@ function regrid_bathymetry(target_grid;
103126
interpolation_passes = 1,
104127
major_basins = 1) # Allow an `Inf` number of "lakes"
105128

106-
filepath = joinpath(dir, filename)
107-
108-
# No need for @root here, because only rank 0 accesses this function
109-
if !isfile(filepath)
110-
Downloads.download(url, filepath; progress=download_progress)
111-
end
112-
129+
filepath = download_bathymetry(; url, dir, filename)
113130
dataset = Dataset(filepath, "r")
114131

115132
FT = eltype(target_grid)
@@ -129,7 +146,7 @@ function regrid_bathymetry(target_grid;
129146
arch = architecture(target_grid)
130147
λ_data = λ_data |> Array{BigFloat}
131148
φ_data = φ_data |> Array{BigFloat}
132-
149+
133150
if !isnothing(height_above_water)
134151
# Overwrite the height of cells above water.
135152
# This has an impact on reconstruction. Greater height_above_water reduces total
@@ -161,8 +178,8 @@ function regrid_bathymetry(target_grid;
161178
native_z = Field{Center, Center, Nothing}(native_grid)
162179
set!(native_z, z_data)
163180
fill_halo_regions!(native_z)
164-
165-
target_z = interpolate_bathymetry_in_passes(native_z, target_grid;
181+
182+
target_z = interpolate_bathymetry_in_passes(native_z, target_grid;
166183
passes = interpolation_passes)
167184

168185
if minimum_depth > 0
@@ -182,7 +199,7 @@ function regrid_bathymetry(target_grid;
182199
return target_z
183200
end
184201

185-
# Here we can either use `regrid!` (three dimensional version) or `interpolate`
202+
# Here we can either use `regrid!` (three dimensional version) or `interpolate!`.
186203
function interpolate_bathymetry_in_passes(native_z, target_grid;
187204
passes = 10)
188205
Nλt, Nφt = Nt = size(target_grid)
@@ -205,7 +222,7 @@ function interpolate_bathymetry_in_passes(native_z, target_grid;
205222
"is finer than the target grid in both horizontal directions.")
206223
return target_z
207224
end
208-
225+
209226
# Interpolate in passes
210227
latitude = y_domain(native_z.grid)
211228
longitude = x_domain(native_z.grid)
@@ -254,8 +271,8 @@ function regrid_bathymetry(target_grid::DistributedGrid; kw...)
254271
arch = architecture(target_grid)
255272
Nx, Ny, _ = size(global_grid)
256273

257-
# If all ranks open a gigantic bathymetry and the memory is
258-
# shared, we could easily have OOM errors.
274+
# If all ranks open a gigantic bathymetry and the memory is
275+
# shared, we could easily have OOM errors.
259276
# We perform the reconstruction only on rank 0 and share the result.
260277
bottom_height = if arch.local_rank == 0
261278
bottom_field = regrid_bathymetry(global_grid; kw...)
@@ -316,7 +333,7 @@ function maybe_extend_longitude(zb_cpu, ::Periodic)
316333
nx = Nx ÷ 2
317334

318335
zb_data = zb_cpu.data[1:Nx, :, 1]
319-
zb_parent = zb_data.parent
336+
zb_parent = zb_data.parent
320337

321338
# Add information on the LHS and to the RHS
322339
zb_parent = vcat(zb_parent[nx:Nx, :], zb_parent, zb_parent[1:nx, :])
@@ -328,7 +345,7 @@ function maybe_extend_longitude(zb_cpu, ::Periodic)
328345
return OffsetArray(zb_parent, xoffsets, yoffsets)
329346
end
330347

331-
remove_major_basins!(zb::OffsetArray, keep_minor_basins) =
348+
remove_major_basins!(zb::OffsetArray, keep_minor_basins) =
332349
remove_minor_basins!(zb.parent, keep_minor_basins)
333350

334351
function remove_minor_basins!(zb, keep_major_basins)
@@ -342,24 +359,24 @@ function remove_minor_basins!(zb, keep_major_basins)
342359
end
343360

344361
water = zb .< 0
345-
362+
346363
connectivity = ImageMorphology.strel(water)
347364
labels = ImageMorphology.label_components(connectivity)
348-
365+
349366
total_elements = zeros(maximum(labels))
350367
label_elements = zeros(maximum(labels))
351368

352369
for e in 1:lastindex(total_elements)
353370
total_elements[e] = length(labels[labels .== e])
354371
label_elements[e] = e
355372
end
356-
373+
357374
mm_basins = [] # major basins indexes
358375
m = 1
359376

360377
# We add basin indexes until we reach the specified number (m == keep_major_basins) or
361-
# we run out of basins to keep -> isempty(total_elements)
362-
while (m <= keep_major_basins) && !isempty(total_elements)
378+
# we run out of basins to keep -> isempty(total_elements)
379+
while (m <= keep_major_basins) && !isempty(total_elements)
363380
next_maximum = findfirst(x -> x == maximum(total_elements), total_elements)
364381
push!(mm_basins, label_elements[next_maximum])
365382
deleteat!(total_elements, next_maximum)
@@ -399,11 +416,11 @@ Returns
399416
400417
- `bottom_height`: The retrieved or generated bathymetry data.
401418
402-
If the specified file exists, the function reads the bathymetry data from the file.
419+
If the specified file exists, the function reads the bathymetry data from the file.
403420
Otherwise, it generates the bathymetry data using the provided grid and saves it to the file before returning it.
404421
"""
405-
function retrieve_bathymetry(grid, filename; kw...)
406-
422+
function retrieve_bathymetry(grid, filename; kw...)
423+
407424
if isfile(filename)
408425
bottom_height = jldopen(filename)["bathymetry"]
409426
else

0 commit comments

Comments
 (0)