Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions examples/ecco_inspect_temperature_salinity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ grid = LatitudeLongitudeGrid(arch; z,
latitude = (-80, 80),
longitude = (0, 360))

bottom_height = regrid_bathymetry(grid;
minimum_depth = 10,
interpolation_passes = 5,
major_basins = 1)

bottom_height = regrid_bathymetry(grid; minimum_depth = 10, major_basins = 1)
grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height))

T = CenterField(grid)
Expand Down
6 changes: 1 addition & 5 deletions examples/ecco_mixed_layer_depth.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ grid = LatitudeLongitudeGrid(arch; z,
latitude = (-80, 80),
longitude = (0, 360))

bottom_height = regrid_bathymetry(grid;
minimum_depth = 10,
interpolation_passes = 5,
major_basins = 1)

bottom_height = regrid_bathymetry(grid; minimum_depth = 10, major_basins = 1)
grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height))

start_date = DateTime(1993, 1, 1)
Expand Down
2 changes: 1 addition & 1 deletion examples/generate_bathymetry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ grid = LatitudeLongitudeGrid(size = (Nλ, Nφ, 1),
# and fills them with land.

h_rough = regrid_bathymetry(grid)
h_smooth = regrid_bathymetry(grid; interpolation_passes = 40)
h_smooth = regrid_bathymetry(grid; smoothing=InterpolationPasses(40))
h_one_basin = regrid_bathymetry(grid; major_basins = 1)
nothing #hide

Expand Down
4 changes: 1 addition & 3 deletions examples/mediterranean_simulation_with_ecco_restoring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ grid = LatitudeLongitudeGrid(GPU();
# ### Bathymetry Interpolation
#
# The script interpolates bathymetric data onto the grid, ensuring that the model accurately represents
# the sea floor's topography. Parameters such as `minimum_depth` and `interpolation_passes`
# are adjusted to refine the bathymetry representation.
# the sea floor's topography. `minimum_depth` is adjusted to refine the bathymetry representation.

bottom_height = regrid_bathymetry(grid,
height_above_water = 1,
minimum_depth = 10,
interpolation_passes = 25,
connected_regions_allowed = 1)

grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height))
Expand Down
1 change: 0 additions & 1 deletion examples/near_global_ocean_simulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ grid = LatitudeLongitudeGrid(arch;

bottom_height = regrid_bathymetry(grid;
minimum_depth = 10meters,
interpolation_passes = 5,
major_basins = 3)

grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height); active_cells_map=true)
Expand Down
1 change: 0 additions & 1 deletion examples/one_degree_simulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ underlying_grid = TripolarGrid(arch;

bottom_height = regrid_bathymetry(underlying_grid;
minimum_depth = 10,
interpolation_passes = 75, # 75 interpolation passes smooth the bathymetry near Florida so that the Gulf Stream is able to flow
major_basins = 2)

# For this bathymetry at this horizontal resolution we need to manually open the Gibraltar strait.
Expand Down
2 changes: 1 addition & 1 deletion experiments/one_degree_simulation/one_degree_simulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Nz = 32
z_faces = exponential_z_faces(; Nz, depth=6000, h=34)
underlying_grid = TripolarGrid(arch; size=(Nx, Ny, Nz), z=z_faces)

bottom_height = regrid_bathymetry(underlying_grid; minimum_depth=30, interpolation_passes=20, major_basins=1)
bottom_height = regrid_bathymetry(underlying_grid; minimum_depth=30, major_basins=1)
view(bottom_height, 73:78, 88:89, 1) .= -1000 # open Gibraltar strait

grid = ImmersedBoundaryGrid(underlying_grid, GridFittedBottom(bottom_height); active_cells_map=true)
Expand Down
89 changes: 42 additions & 47 deletions src/Bathymetry.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Bathymetry

export regrid_bathymetry, retrieve_bathymetry, download_bathymetry
export regrid_bathymetry, retrieve_bathymetry, download_bathymetry, InterpolationPasses

using ImageMorphology
using ..DataWrangling: download_progress
Expand Down Expand Up @@ -66,7 +66,7 @@ end
dir = download_bathymetry_cache,
url = ClimaOcean.Bathymetry.etopo_url,
filename = "ETOPO_2022_v1_60s_N90W180_surface.nc",
interpolation_passes = 1,
smoothing = nothing
major_basins = 1)

Return bathymetry associated with the NetCDF file at `path = joinpath(dir, filename)` regridded onto `target_grid`.
Expand All @@ -93,9 +93,8 @@ Keyword Arguments
2. `lon` vector of longitude nodes
3. `z` matrix of depth values

- `interpolation_passes`: regridding/interpolation passes. The bathymetry is interpolated in
`interpolation_passes - 1` intermediate steps. The more the interpolation
steps the smoother the final bathymetry becomes.
- `smoothing`: smoothing method for bathymetry.
Default: nothing.

Example
=======
Expand Down Expand Up @@ -123,7 +122,7 @@ function regrid_bathymetry(target_grid;
dir = download_bathymetry_cache,
url = etopo_url,
filename = "ETOPO_2022_v1_60s_N90W180_surface.nc",
interpolation_passes = 1,
smoothing = nothing,
major_basins = 1) # Allow an `Inf` number of "lakes"

filepath = download_bathymetry(; url, dir, filename)
Expand Down Expand Up @@ -179,8 +178,7 @@ function regrid_bathymetry(target_grid;
set!(native_z, z_data)
fill_halo_regions!(native_z)

target_z = interpolate_bathymetry_in_passes(native_z, target_grid;
passes = interpolation_passes)
target_z = interpolate_bathymetry(native_z, target_grid, smoothing)

if minimum_depth > 0
zi = interior(target_z, :, :, 1)
Expand All @@ -200,67 +198,64 @@ function regrid_bathymetry(target_grid;
end

# Here we can either use `regrid!` (three dimensional version) or `interpolate!`.
function interpolate_bathymetry_in_passes(native_z, target_grid;
passes = 10)
Nλt, Nφt = Nt = size(target_grid)
Nλn, Nφn = Nn = size(native_z)

resxt = minimum_xspacing(target_grid)
resyt = minimum_yspacing(target_grid)

resxn = minimum_xspacing(native_z.grid)
resyn = minimum_yspacing(native_z.grid)

# Check whether we are refining the grid in any directions.
# If so, skip interpolation passes, as they are not needed.
if resxt < resxn || resyt < resyn
target_z = Field{Center, Center, Nothing}(target_grid)
interpolate!(target_z, native_z)
@info string("Skipping passes for interpolating bathymetry of size $Nn ", '\n',
"to target grid of size $Nt. Interpolation passes may only ", '\n',
"be used to coarsen bathymetry and require that the bathymetry ", '\n',
"is finer than the target grid in both horizontal directions.")
return target_z
function interpolate_bathymetry(user_z, target_grid, smoothing)
smooth_z = smooth_bathymetry(user_z, target_grid, smoothing)
target_z = Field{Center, Center, Nothing}(target_grid)
interpolate!(target_z, smooth_z)
return target_z
end

smooth_bathymetry(z, ::Nothing) = z

struct InterpolationPasses
passes :: Int

function InterpolationPasses(passes)
if passes < 1
throw(ArgumentError("`passes` must be larger than 0"))
elseif !isinteger(passes)
throw(ArgumentError("`passes` must be an integer"))
end

return new(passes)
end
end

# Interpolate in passes
latitude = y_domain(native_z.grid)
longitude = x_domain(native_z.grid)
function smooth_bathymetry(user_z, target_grid, smoothing::InterpolationPasses)
passes = smoothing.passes
Nλt, Nφt = Nt = size(target_grid)
Nλn, Nφn = Nn = size(user_z)

ΔNλ = floor((Nλn - Nλt) / passes)
ΔNφ = floor((Nφn - Nφt) / passes)
# Interpolate in passes
longitude = x_domain(user_z.grid)
latitude = y_domain(user_z.grid)

= [Nλn - ΔNλ * pass for pass in 1:passes-1]
= [Nφn - ΔNφ * pass for pass in 1:passes-1]
ΔNλ = floor((Nλn - Nλt) / (passes - 1))
ΔNφ = floor((Nφn - Nφt) / (passes - 1))

Nλ = Int[Nλ..., Nλt]
Nφ = Int[Nφ..., Nφt]
Nλ = [Nλn - ΔNλ * pass for pass in 1:passes]
Nφ = [Nφn - ΔNφ * pass for pass in 1:passes]

old_z = native_z
old_z = user_z
TX, TY = topology(target_grid)

for pass = 1:passes - 1
for pass = 1:passes
new_size = (Nλ[pass], Nφ[pass], 1)

@debug "Bathymetry interpolation pass $pass with size $new_size"

new_grid = LatitudeLongitudeGrid(architecture(target_grid), Float32,
size = new_size,
latitude = (latitude[1], latitude[2]),
latitude = (latitude[1], latitude[2]),
longitude = (longitude[1], longitude[2]),
z = (0, 1),
topology = (TX, TY, Bounded))

new_z = Field{Center, Center, Nothing}(new_grid)

interpolate!(new_z, old_z)
old_z = new_z
end

target_z = Field{Center, Center, Nothing}(target_grid)
interpolate!(target_z, old_z)

return target_z
return new_z
end

# Regridding bathymetry for distributed grids, we handle the whole process
Expand Down
14 changes: 1 addition & 13 deletions test/test_bathymetry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,14 @@ using ClimaOcean.Bathymetry: remove_minor_basins!
# of -1000 meters
@test mean(view(bottom_height, 51:100, :, 1)) == -1000

grid = LatitudeLongitudeGrid(arch;
size = (200, 200, 10),
longitude = (0, 2),
latitude = (-0.1, 0.1),
z = (-6000, 0))

control_bottom_height = regrid_bathymetry(grid)
interpolated_bottom_height = regrid_bathymetry(grid; interpolation_passes=100)

# Testing that multiple passes do not change the solution when refining the grid
@test parent(control_bottom_height) == parent(interpolated_bottom_height)

grid = LatitudeLongitudeGrid(arch;
size = (200, 200, 10),
longitude = (0, 100),
latitude = (-10, 50),
z = (-6000, 0))

control_bottom_height = regrid_bathymetry(grid)
interpolated_bottom_height = regrid_bathymetry(grid; interpolation_passes=10)
interpolated_bottom_height = regrid_bathymetry(grid; smoothing=InterpolationPasses(10))

# Testing that multiple passes _do_ change the solution when coarsening the grid
@test parent(control_bottom_height) != parent(interpolated_bottom_height)
Expand Down
1 change: 0 additions & 1 deletion test/test_diagnostics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ using ClimaOcean.Diagnostics: MixedLayerDepthField, MixedLayerDepthOperand

bottom_height = regrid_bathymetry(grid;
minimum_depth = 10,
interpolation_passes = 5,
major_basins = 1)

grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height))
Expand Down
6 changes: 2 additions & 4 deletions test/test_distributed_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ end

global_height = regrid_bathymetry(global_grid;
dir = "./",
filename = "trivial_bathymetry.nc",
interpolation_passes=10)
filename = "trivial_bathymetry.nc")

arch_x = Distributed(CPU(), partition=Partition(4, 1))
arch_y = Distributed(CPU(), partition=Partition(1, 4))
Expand All @@ -75,8 +74,7 @@ end

local_height = regrid_bathymetry(local_grid;
dir = "./",
filename = "trivial_bathymetry.nc",
interpolation_passes=10)
filename = "trivial_bathymetry.nc")

Nx, Ny, _ = size(local_grid)
rx, ry, _ = arch.local_index
Expand Down
1 change: 0 additions & 1 deletion test/test_ocean_sea_ice_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ using ClimaSeaIce.Rheologies

bottom_height = regrid_bathymetry(grid;
minimum_depth = 10,
interpolation_passes = 20,
major_basins = 1)

grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height); active_cells_map=true)
Expand Down
Loading