Skip to content
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

Fix _immered_cell and adapt for PartialCellBottom #3682

Merged
merged 25 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d9529a2
fix a bug in the adapt
simone-silvestri Aug 5, 2024
0992e0a
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 8, 2024
6e5b307
first fix
simone-silvestri Aug 8, 2024
1bdf889
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 8, 2024
f1f249d
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 14, 2024
292f556
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 15, 2024
6b47133
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 29, 2024
ed6d252
bugfix
simone-silvestri Aug 29, 2024
ffca52b
these should be all the bugs, still need to add the tests
simone-silvestri Aug 29, 2024
0fd3986
another bugfix
simone-silvestri Aug 29, 2024
c55f8c3
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Aug 29, 2024
ee46994
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Sep 4, 2024
9c00248
Merge branch 'main' into ss/adapt-bottom-height
glwagner Sep 25, 2024
0ed035b
Clamp bottom_height to top and bottom of grid
glwagner Sep 25, 2024
00ffa57
Bugfix
glwagner Sep 25, 2024
e8f6bc3
Merge remote-tracking branch 'origin/glw/clamp-bottom-height' into ss…
glwagner Sep 25, 2024
2ed8f01
Implement clamping for both GF and PC bottom
glwagner Sep 25, 2024
a200fd0
Convert internal tide example to use extension
glwagner Sep 25, 2024
47eeff0
apply_regionally *sigh*
glwagner Sep 25, 2024
6f796a4
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Sep 25, 2024
9b1244a
Disambiguate
glwagner Sep 25, 2024
7ccd608
Merge branch 'ss/adapt-bottom-height' of https://github.com/CliMA/Oce…
glwagner Sep 25, 2024
9807bd0
using CairoMakie
simone-silvestri Sep 25, 2024
8d79478
Merge branch 'main' into ss/adapt-bottom-height
simone-silvestri Sep 27, 2024
0f39bc8
Merge branch 'main' into ss/adapt-bottom-height
glwagner Sep 27, 2024
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
17 changes: 9 additions & 8 deletions examples/internal_tide.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

using Oceananigans
using Oceananigans.Units
using Oceananigans.ImmersedBoundaries: PartialCellBottom

# ## Grid

Expand Down Expand Up @@ -46,7 +47,7 @@ width = 20kilometers
hill(x) = h₀ * exp(-x^2 / 2width^2)
bottom(x) = - H + hill(x)

grid = ImmersedBoundaryGrid(underlying_grid, GridFittedBottom(bottom))
grid = ImmersedBoundaryGrid(underlying_grid, PartialCellBottom(bottom))

# Let's see how the domain with the bathymetry is.

Expand Down Expand Up @@ -132,7 +133,7 @@ bᵢ(x, z) = Nᵢ² * z

set!(model, u=uᵢ, b=bᵢ)

# Now let's built a `Simulation`.
# Now let's build a `Simulation`.

Δt = 5minutes
stop_time = 4days
Expand Down Expand Up @@ -234,9 +235,9 @@ n = Observable(1)
title = @lift @sprintf("t = %1.2f days = %1.2f T₂",
round(times[$n] / day, digits=2) , round(times[$n] / T₂, digits=2))

u′ = @lift u′_t[$n]
wₙ = @lift w_t[$n]
= @lift N²_t[$n]
u′n = @lift u′_t[$n]
wn = @lift w_t[$n]
n = @lift N²_t[$n]

axis_kwargs = (xlabel = "x [km]",
ylabel = "z [km]",
Expand All @@ -248,15 +249,15 @@ fig = Figure(size = (700, 900))
fig[1, :] = Label(fig, title, fontsize=24, tellwidth=false)

ax_u = Axis(fig[2, 1]; title = "u'-velocity", axis_kwargs...)
hm_u = heatmap!(ax_u, xu, zu, u′ₙ; colorrange = (-umax, umax), colormap = :balance)
hm_u = heatmap!(ax_u, xu, zu, u′n; nan_color=:gray, colorrange=(-umax, umax), colormap=:balance)
Colorbar(fig[2, 2], hm_u, label = "m s⁻¹")

ax_w = Axis(fig[3, 1]; title = "w-velocity", axis_kwargs...)
hm_w = heatmap!(ax_w, xw, zw, wₙ; colorrange = (-wmax, wmax), colormap = :balance)
hm_w = heatmap!(ax_w, xw, zw, wn; nan_color=:gray, colorrange=(-wmax, wmax), colormap=:balance)
Colorbar(fig[3, 2], hm_w, label = "m s⁻¹")

ax_N² = Axis(fig[4, 1]; title = "stratification N²", axis_kwargs...)
hm_N² = heatmap!(ax_N², xN², zN², N²ₙ; colorrange = (0.9Nᵢ², 1.1Nᵢ²), colormap = :thermal)
hm_N² = heatmap!(ax_N², xN², zN², N²n; nan_color=:gray, colorrange=(0.9Nᵢ², 1.1Nᵢ²), colormap=:magma)
Colorbar(fig[4, 2], hm_N², label = "s⁻²")

fig
Expand Down
17 changes: 17 additions & 0 deletions src/ImmersedBoundaries/abstract_grid_fitted_boundary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,20 @@ const AGFB = AbstractGridFittedBoundary
@inline immersed_cell(i, j, k, grid::AbstractGrid{<:Any, Flat, Flat, Flat}, ib::AGFB) = _immersed_cell(1, 1, 1, grid, ib)
end

function clamp_bottom_height!(bottom_field, grid)
launch!(architecture(grid), grid, :xy, _clamp_bottom_height!, bottom_field, grid)
return nothing
end

const c = Center()
const f = Face()

@kernel function _clamp_bottom_height!(z, grid)
i, j = @index(Global, NTuple)
Nz = size(grid, 3)
zmin = znode(i, j, 1, grid, c, c, f)
zmax = znode(i, j, Nz+1, grid, c, c, f)
@inbounds z[i, j, 1] = clamp(z[i, j, 1], zmin, zmax)
end


13 changes: 7 additions & 6 deletions src/ImmersedBoundaries/grid_fitted_bottom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ Keyword Arguments
GridFittedBottom(bottom_height) = GridFittedBottom(bottom_height, CenterImmersedCondition())

function Base.summary(ib::GridFittedBottom)
hmax = maximum(ib.bottom_height)
hmin = minimum(ib.bottom_height)
hmean = mean(ib.bottom_height)
zmax = maximum(ib.bottom_height)
zmin = minimum(ib.bottom_height)
zmean = mean(ib.bottom_height)

summary1 = "GridFittedBottom("

summary2 = string("mean(z)=", prettysummary(hmean),
", min(z)=", prettysummary(hmin),
", max(z)=", prettysummary(hmax))
summary2 = string("mean(z)=", prettysummary(zmean),
", min(z)=", prettysummary(zmin),
", max(z)=", prettysummary(zmax))

summary3 = ")"

Expand All @@ -87,6 +87,7 @@ Computes `ib.bottom_height` and wraps it in a Field.
function ImmersedBoundaryGrid(grid, ib::GridFittedBottom)
bottom_field = Field{Center, Center, Nothing}(grid)
set!(bottom_field, ib.bottom_height)
@apply_regionally clamp_bottom_height!(bottom_field, grid)
fill_halo_regions!(bottom_field)
new_ib = GridFittedBottom(bottom_field, ib.immersed_condition)
TX, TY, TZ = topology(grid)
Expand Down
76 changes: 54 additions & 22 deletions src/ImmersedBoundaries/partial_cell_bottom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ struct PartialCellBottom{H, E} <: AbstractGridFittedBottom{H}
minimum_fractional_cell_height :: E
end

const PCBIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Any, <:Any, <:Any, <:PartialCellBottom}
const PCBIBG{FT, TX, TY, TZ} = ImmersedBoundaryGrid{FT, TX, TY, TZ, <:Any, <:PartialCellBottom} where {FT, TX, TY, TZ}

function Base.summary(ib::PartialCellBottom)
hmax = maximum(parent(ib.bottom_height))
hmin = minimum(parent(ib.bottom_height))
hmean = mean(parent(ib.bottom_height))
zmax = maximum(parent(ib.bottom_height))
zmin = minimum(parent(ib.bottom_height))
zmean = mean(parent(ib.bottom_height))

summary1 = "PartialCellBottom("

summary2 = string("mean(z)=", prettysummary(hmean),
", min(z)=", prettysummary(hmin),
", max(z)=", prettysummary(hmax),
summary2 = string("mean(zb)=", prettysummary(zmean),
", min(zb)=", prettysummary(zmin),
", max(zb)=", prettysummary(zmax),
", ϵ=", prettysummary(ib.minimum_fractional_cell_height))

summary3 = ")"
Expand Down Expand Up @@ -63,6 +63,7 @@ end
function ImmersedBoundaryGrid(grid, ib::PartialCellBottom)
bottom_field = Field{Center, Center, Nothing}(grid)
set!(bottom_field, ib.bottom_height)
@apply_regionally clamp_bottom_height!(bottom_field, grid)
fill_halo_regions!(bottom_field)
new_ib = PartialCellBottom(bottom_field, ib.minimum_fractional_cell_height)
TX, TY, TZ = topology(grid)
Expand All @@ -77,32 +78,49 @@ function on_architecture(arch, ib::PartialCellBottom{<:Field})
return PartialCellBottom(new_bottom_height, ib.minimum_fractional_cell_height)
end

Adapt.adapt_structure(to, ib::PartialCellBottom) = PartialCellBottom(adapt(to, ib.bottom_height.data),
Adapt.adapt_structure(to, ib::PartialCellBottom) = PartialCellBottom(adapt(to, ib.bottom_height),
ib.minimum_fractional_cell_height)

on_architecture(to, ib::PartialCellBottom) = PartialCellBottom(on_architecture(to, ib.bottom_height.data),
on_architecture(to, ib::PartialCellBottom) = PartialCellBottom(on_architecture(to, ib.bottom_height),
on_architecture(to, ib.minimum_fractional_cell_height))

"""

--x--
∘ k+1
k+1 --x-- ↑ <- node z
∘ k | Δz
k --x-- ↓
immersed underlying

--x-- --x--


∘ ↑ ∘ k+1
|
|
k+1 --x-- | k+1 --x-- ↑ <- node z
∘ ↓ |
zb ⋅⋅x⋅⋅ |
|
∘ k | Δz
|
|
k --x-- ↓

Criterion is h ≥ z - ϵ Δz
Criterion is zb ≥ z - ϵ Δz

"""
@inline function _immersed_cell(i, j, k, underlying_grid, ib::PartialCellBottom)
# Face node above current cell
z = znode(i, j, k+1, underlying_grid, c, c, f)
h = @inbounds ib.bottom_height[i, j, 1]
return z ≤ h
# Face node below current cell
z = znode(i, j, k, underlying_grid, c, c, f)
zb = @inbounds ib.bottom_height[i, j, 1]
ϵ = ib.minimum_fractional_cell_height
# z + Δz is equal to the face above the current cell
Δz = Δzᶜᶜᶜ(i, j, k, underlying_grid)
return (z + Δz * (1 - ϵ)) ≤ zb
end

@inline bottom_cell(i, j, k, ibg::PCBIBG) = !immersed_cell(i, j, k, ibg.underlying_grid, ibg.immersed_boundary) &
immersed_cell(i, j, k-1, ibg.underlying_grid, ibg.immersed_boundary)
@inline function bottom_cell(i, j, k, ibg::PCBIBG)
grid = ibg.underlying_grid
ib = ibg.immersed_boundary
# This one's not immersed, but the next one down is
return !immersed_cell(i, j, k, grid, ib) & immersed_cell(i, j, k-1, grid, ib)
end

@inline function Δzᶜᶜᶜ(i, j, k, ibg::PCBIBG)
underlying_grid = ibg.underlying_grid
Expand Down Expand Up @@ -145,4 +163,18 @@ end
@inline Δzᶜᶠᶠ(i, j, k, ibg::PCBIBG) = min(Δzᶜᶜᶠ(i, j-1, k, ibg), Δzᶜᶜᶠ(i, j, k, ibg))
@inline Δzᶠᶠᶠ(i, j, k, ibg::PCBIBG) = min(Δzᶠᶜᶠ(i, j-1, k, ibg), Δzᶠᶜᶠ(i, j, k, ibg))

# Make sure Δz works for horizontally-Flat topologies.
# (There's no point in using z-Flat with PartialCellBottom).
XFlatPCBIBG = ImmersedBoundaryGrid{<:Any, <:Flat, <:Any, <:Any, <:Any, <:PartialCellBottom}
YFlatPCBIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Flat, <:Any, <:Any, <:PartialCellBottom}

@inline Δzᶠᶜᶜ(i, j, k, ibg::XFlatPCBIBG) = Δzᶜᶜᶜ(i, j, k, ibg)
@inline Δzᶠᶜᶠ(i, j, k, ibg::XFlatPCBIBG) = Δzᶜᶜᶠ(i, j, k, ibg)
@inline Δzᶜᶠᶜ(i, j, k, ibg::YFlatPCBIBG) = Δzᶜᶜᶜ(i, j, k, ibg)

@inline Δzᶜᶠᶠ(i, j, k, ibg::YFlatPCBIBG) = Δzᶜᶜᶠ(i, j, k, ibg)
@inline Δzᶠᶠᶜ(i, j, k, ibg::XFlatPCBIBG) = Δzᶜᶠᶜ(i, j, k, ibg)
@inline Δzᶠᶠᶜ(i, j, k, ibg::YFlatPCBIBG) = Δzᶠᶜᶜ(i, j, k, ibg)

@inline z_bottom(i, j, ibg::PCBIBG) = @inbounds ibg.immersed_boundary.bottom_height[i, j, 1]

16 changes: 16 additions & 0 deletions test/test_immersed_boundary_grid.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
include("dependencies_for_runtests.jl")

grid = RectilinearGrid(; size=(2, 2, 2), extent = (1, 1, 1))

@testset "Testing Immersed Boundaries" begin

@info "Testing the immersed boundary construction..."

bottom(x, y) = -1 + 0.5 * exp(-x^2 - y^2)
ibg = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom))

# Unit test (bottom is at the right position)

@info "Testing stably stratified initial conditions..."

end