-
Notifications
You must be signed in to change notification settings - Fork 216
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
static_column_depth
interface and numerical bottom height in AbstractGridFittedBottom
#3841
Changes from all commits
4044e16
b83a6ae
5ebaa84
f9ad227
cbdb713
7f08768
4b7926f
6b7b27c
fdee366
d1c145c
dbb411a
3ec05df
4e4d40b
a6362ee
3bce6fc
0fa1a67
135cac3
156dada
04e7170
9258572
9df333a
053b26f
61b7e7f
1098c58
9e35af6
ac7c96d
f8d5c18
fd8a028
f518d41
983b956
dfada79
2705b03
ca935b6
cc9cd4f
495f6ea
45b5cd4
d381037
b8401cc
cfd5c42
3ecd318
b967754
3f36846
9ff305e
6046d2d
8106a70
a10df16
5ee7623
9777ee6
1d219af
238fa74
90dfa7a
f2402f0
55d7432
849c253
510a858
926feda
aea0601
dfd0b30
fe2d552
5227a13
1225061
1652c6b
9323203
37b17ff
2ac8cde
0eb2720
50d0ec3
6e183bd
d66baf2
c57a321
cfc6ad0
bd84d38
c56b15b
371a45b
e30973f
e4cb16e
0c1f01c
88c5d3a
bec1cd1
75546af
5f49ec0
9b334af
f8c6401
1dc42bb
5a870e7
9e63f56
59548f8
642cfd9
db58da1
4cee49a
a46b25d
4dffbe5
9c3c6cd
3b28ecb
00f87a4
7126c7c
733ab2b
2dbf1a0
a4b129a
29f7d69
56ded6a
3154a34
3803ff3
2813769
4b7d9ed
3ab5bf3
7741b9e
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 |
---|---|---|
|
@@ -18,14 +18,14 @@ abstract type AbstractGridFittedBottom{H} <: AbstractGridFittedBoundary end | |
struct CenterImmersedCondition end | ||
struct InterfaceImmersedCondition end | ||
|
||
Base.summary(::CenterImmersedCondition) = "CenterImmersedCondition" | ||
Base.summary(::InterfaceImmersedCondition) = "InterfaceImmersedCondition" | ||
|
||
struct GridFittedBottom{H, I} <: AbstractGridFittedBottom{H} | ||
bottom_height :: H | ||
immersed_condition :: I | ||
end | ||
|
||
Base.summary(::CenterImmersedCondition) = "CenterImmersedCondition" | ||
Base.summary(::InterfaceImmersedCondition) = "InterfaceImmersedCondition" | ||
|
||
const GFBIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Any, <:Any, <:Any, <:GridFittedBottom} | ||
|
||
""" | ||
|
@@ -36,6 +36,7 @@ Return a bottom immersed boundary. | |
Keyword Arguments | ||
================= | ||
|
||
|
||
* `bottom_height`: an array or function that gives the height of the | ||
bottom in absolute ``z`` coordinates. | ||
|
||
|
@@ -72,50 +73,77 @@ Base.summary(ib::GridFittedBottom{<:Function}) = @sprintf("GridFittedBottom(%s)" | |
function Base.show(io::IO, ib::GridFittedBottom) | ||
print(io, summary(ib), '\n') | ||
print(io, "├── bottom_height: ", prettysummary(ib.bottom_height), '\n') | ||
print(io, "└── immersed_condition: ", summary(ib.immersed_condition)) | ||
end | ||
|
||
@inline z_bottom(i, j, ibg::GFBIBG) = @inbounds ibg.immersed_boundary.bottom_height[i, j, 1] | ||
on_architecture(arch, ib::GridFittedBottom) = GridFittedBottom(on_architecture(arch, ib.bottom_height), ib.immersed_condition) | ||
|
||
function on_architecture(arch, ib::GridFittedBottom{<:Field}) | ||
architecture(ib.bottom_height) == arch && return ib | ||
arch_grid = on_architecture(arch, ib.bottom_height.grid) | ||
new_bottom_height = Field{Center, Center, Nothing}(arch_grid) | ||
set!(new_bottom_height, ib.bottom_height) | ||
fill_halo_regions!(new_bottom_height) | ||
return GridFittedBottom(new_bottom_height, ib.immersed_condition) | ||
end | ||
|
||
Adapt.adapt_structure(to, ib::GridFittedBottom) = GridFittedBottom(adapt(to, ib.bottom_height), adapt(to, ib.immersed_condition)) | ||
|
||
""" | ||
ImmersedBoundaryGrid(grid, ib::GridFittedBottom) | ||
|
||
Return a grid with `GridFittedBottom` immersed boundary (`ib`). | ||
|
||
Computes `ib.bottom_height` and wraps it in a Field. | ||
Computes `ib.bottom_height` and wraps it in a Field. `ib.bottom_height` is the z-coordinate of top-most interface | ||
of the last ``immersed`` cell in the column. | ||
""" | ||
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) | ||
@apply_regionally compute_numerical_bottom_height!(bottom_field, grid, ib) | ||
fill_halo_regions!(bottom_field) | ||
new_ib = GridFittedBottom(bottom_field, ib.immersed_condition) | ||
new_ib = GridFittedBottom(bottom_field) | ||
TX, TY, TZ = topology(grid) | ||
return ImmersedBoundaryGrid{TX, TY, TZ}(grid, new_ib) | ||
end | ||
|
||
@inline function _immersed_cell(i, j, k, underlying_grid, ib::GridFittedBottom{<:Any, <:InterfaceImmersedCondition}) | ||
z = znode(i, j, k+1, underlying_grid, c, c, f) | ||
h = @inbounds ib.bottom_height[i, j, 1] | ||
return z ≤ h | ||
compute_numerical_bottom_height!(bottom_field, grid, ib) = | ||
launch!(architecture(grid), grid, :xy, _compute_numerical_bottom_height!, bottom_field, grid, ib) | ||
|
||
@kernel function _compute_numerical_bottom_height!(bottom_field, grid, ib::GridFittedBottom) | ||
i, j = @index(Global, NTuple) | ||
zb = @inbounds bottom_field[i, j, 1] | ||
@inbounds bottom_field[i, j, 1] = znode(i, j, 1, grid, c, c, f) | ||
condition = ib.immersed_condition | ||
for k in 1:grid.Nz | ||
z⁺ = znode(i, j, k+1, grid, c, c, f) | ||
z = znode(i, j, k, grid, c, c, c) | ||
bottom_cell = ifelse(condition isa CenterImmersedCondition, z ≤ zb, z⁺ ≤ zb) | ||
@inbounds bottom_field[i, j, 1] = ifelse(bottom_cell, z⁺, zb) | ||
end | ||
end | ||
|
||
@inline function _immersed_cell(i, j, k, underlying_grid, ib::GridFittedBottom{<:Any, <:CenterImmersedCondition}) | ||
z = znode(i, j, k, underlying_grid, c, c, c) | ||
h = @inbounds ib.bottom_height[i, j, 1] | ||
return z ≤ h | ||
@inline function _immersed_cell(i, j, k, underlying_grid, ib::GridFittedBottom) | ||
z = znode(i, j, k, underlying_grid, c, c, c) | ||
zb = @inbounds ib.bottom_height[i, j, 1] | ||
return z ≤ zb | ||
end | ||
|
||
on_architecture(arch, ib::GridFittedBottom) = GridFittedBottom(ib.bottom_height, ib.immersed_condition) | ||
##### | ||
##### Static column depth | ||
##### | ||
|
||
function on_architecture(arch, ib::GridFittedBottom{<:Field}) | ||
architecture(ib.bottom_height) == arch && return ib | ||
arch_grid = on_architecture(arch, ib.bottom_height.grid) | ||
new_bottom_height = Field{Center, Center, Nothing}(arch_grid) | ||
set!(new_bottom_height, ib.bottom_height) | ||
fill_halo_regions!(new_bottom_height) | ||
return GridFittedBottom(new_bottom_height, ib.immersed_condition) | ||
end | ||
const AGFBIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Any, <:Any, <:Any, <:AbstractGridFittedBottom} | ||
|
||
@inline static_column_depthᶜᶜᵃ(i, j, ibg::AGFBIBG) = @inbounds znode(i, j, ibg.Nz+1, ibg, c, c, f) - ibg.immersed_boundary.bottom_height[i, j, 1] | ||
@inline static_column_depthᶜᶠᵃ(i, j, ibg::AGFBIBG) = min(static_column_depthᶜᶜᵃ(i, j-1, ibg), static_column_depthᶜᶜᵃ(i, j, ibg)) | ||
@inline static_column_depthᶠᶜᵃ(i, j, ibg::AGFBIBG) = min(static_column_depthᶜᶜᵃ(i-1, j, ibg), static_column_depthᶜᶜᵃ(i, j, ibg)) | ||
@inline static_column_depthᶠᶠᵃ(i, j, ibg::AGFBIBG) = min(static_column_depthᶠᶜᵃ(i, j-1, ibg), static_column_depthᶠᶜᵃ(i, j, ibg)) | ||
|
||
# Make sure column_height works for horizontally-Flat topologies. | ||
XFlatAGFIBG = ImmersedBoundaryGrid{<:Any, <:Flat, <:Any, <:Any, <:Any, <:AbstractGridFittedBottom} | ||
YFlatAGFIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Flat, <:Any, <:Any, <:AbstractGridFittedBottom} | ||
|
||
Adapt.adapt_structure(to, ib::GridFittedBottom) = GridFittedBottom(adapt(to, ib.bottom_height), | ||
ib.immersed_condition) | ||
@inline static_column_depthᶠᶜᵃ(i, j, ibg::XFlatAGFIBG) = static_column_depthᶜᶜᵃ(i, j, ibg) | ||
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. when this happens it could suggest that this should be more like static_column_depth(i, j, grid, lx, ly) |
||
@inline static_column_depthᶜᶠᵃ(i, j, ibg::YFlatAGFIBG) = static_column_depthᶜᶜᵃ(i, j, ibg) | ||
@inline static_column_depthᶠᶠᵃ(i, j, ibg::XFlatAGFIBG) = static_column_depthᶜᶠᵃ(i, j, ibg) | ||
@inline static_column_depthᶠᶠᵃ(i, j, ibg::YFlatAGFIBG) = static_column_depthᶠᶜᵃ(i, j, ibg) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,13 +63,42 @@ 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) | ||
@apply_regionally compute_numerical_bottom_height!(bottom_field, grid, ib) | ||
fill_halo_regions!(bottom_field) | ||
new_ib = PartialCellBottom(bottom_field, ib.minimum_fractional_cell_height) | ||
TX, TY, TZ = topology(grid) | ||
return ImmersedBoundaryGrid{TX, TY, TZ}(grid, new_ib) | ||
end | ||
|
||
@kernel function _compute_numerical_bottom_height!(bottom_field, grid, ib::PartialCellBottom) | ||
i, j = @index(Global, NTuple) | ||
|
||
# Save analytical bottom height | ||
zb = @inbounds bottom_field[i, j, 1] | ||
|
||
# Cap bottom height at Lz and at rnode(i, j, grid.Nz+1, grid, c, c, f) | ||
domain_bottom = znode(i, j, 1, grid, c, c, f) | ||
domain_top = znode(i, j, grid.Nz+1, grid, c, c, f) | ||
@inbounds bottom_field[i, j, 1] = clamp(zb, domain_bottom, domain_top) | ||
adjusted_zb = bottom_field[i, j, 1] | ||
|
||
ϵ = ib.minimum_fractional_cell_height | ||
|
||
for k in 1:grid.Nz | ||
z⁻ = znode(i, j, k, grid, c, c, f) | ||
z⁺ = znode(i, j, k+1, grid, c, c, f) | ||
Δz = Δzᶜᶜᶜ(i, j, k, grid) | ||
bottom_cell = (z⁻ ≤ zb) & (z⁺ ≥ zb) | ||
capped_zb = min(z⁺ - ϵ * Δz, zb) | ||
|
||
# If the size of the bottom cell is less than ϵ Δz, | ||
# we enforce a minimum size of ϵ Δz. | ||
adjusted_zb = ifelse(bottom_cell, capped_zb, zb) | ||
end | ||
|
||
@inbounds bottom_field[i, j, 1] = adjusted_zb | ||
end | ||
|
||
function on_architecture(arch, ib::PartialCellBottom{<:Field}) | ||
architecture(ib.bottom_height) == arch && return ib | ||
arch_grid = on_architecture(arch, ib.bottom_height.grid) | ||
|
@@ -106,13 +135,12 @@ Criterion is zb ≥ z - ϵ Δz | |
|
||
""" | ||
@inline function _immersed_cell(i, j, k, underlying_grid, ib::PartialCellBottom) | ||
# Face node below current cell | ||
z = znode(i, j, k, underlying_grid, c, c, f) | ||
zb = @inbounds ib.bottom_height[i, j, 1] | ||
z⁺ = znode(i, j, k+1, underlying_grid, c, c, f) | ||
ϵ = 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 | ||
z★ = z⁺ - Δz * ϵ | ||
zb = @inbounds ib.bottom_height[i, j, 1] | ||
return z★ < zb | ||
end | ||
|
||
@inline function bottom_cell(i, j, k, ibg::PCBIBG) | ||
|
@@ -129,15 +157,14 @@ end | |
# Get node at face above and defining nodes on c,c,f | ||
z = znode(i, j, k+1, underlying_grid, c, c, f) | ||
|
||
# Get bottom height and fractional Δz parameter | ||
h = @inbounds ib.bottom_height[i, j, 1] | ||
ϵ = ibg.immersed_boundary.minimum_fractional_cell_height | ||
# Get bottom z-coordinate and fractional Δz parameter | ||
zb = @inbounds ib.bottom_height[i, j, 1] | ||
|
||
# Are we in a bottom cell? | ||
at_the_bottom = bottom_cell(i, j, k, ibg) | ||
|
||
full_Δz = Δzᶜᶜᶜ(i, j, k, ibg.underlying_grid) | ||
partial_Δz = max(ϵ * full_Δz, z - h) | ||
full_Δz = Δzᶜᶜᶜ(i, j, k, ibg.underlying_grid) | ||
partial_Δz = z - zb | ||
Comment on lines
+166
to
+167
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. This should go in a different PR. 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. The new numerical bottom height is located at by convention at 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. actually, there is a bug here with how the immersed bottom height is computed. I have corrected it 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. i just dont understand how this is related to a PR that implements a new function called |
||
|
||
return ifelse(at_the_bottom, partial_Δz, full_Δz) | ||
end | ||
|
@@ -175,6 +202,3 @@ YFlatPCBIBG = ImmersedBoundaryGrid{<:Any, <:Any, <:Flat, <:Any, <:Any, <:Partial | |
@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] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this still useful? Why delete it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved it in the
TurbulenceClosures
module where alsoz_top
andheight_above_bottom
are defined. I think it's cleaner to have all these functions in the same place. If I have to guess why they were not is because theImmersedBoundaries
module was defined after theTurbulenceClosures
module. Since this is not the case anymore, this is a bit of a cleanup.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok so its unrelated to the static column depth? I feel z_bottom belongs in the Grids module. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider that it has to be extended for different immersed boundary implementation so it depends on partial cell bottom, etc.
The original implementation may not have been optimal, but since we are moving things around here, I think we should try to improve on the original organization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am ok with moving all these functions in the Grids module, shall we do it in this PR?