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

PolarBoundaryCondition for tracer + views for AbstractOperations #3953

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9dddf39
add this check
simone-silvestri Nov 22, 2024
95e6612
flux boundary conditions not working
simone-silvestri Nov 22, 2024
3b03288
default polar BC for latitudelongitude grid
simone-silvestri Nov 22, 2024
ce3fef1
polar boundary conditions
simone-silvestri Nov 22, 2024
83a23e1
update
simone-silvestri Nov 22, 2024
09ce40b
update
simone-silvestri Nov 22, 2024
755b3bc
will this work?
simone-silvestri Nov 22, 2024
e2dbac9
Merge branch 'ss/top-boundary-condition' of github.com:CliMA/Oceanani…
simone-silvestri Nov 22, 2024
4c13313
update boundary conditions
simone-silvestri Nov 22, 2024
8004cb5
add offsetarrays
simone-silvestri Nov 22, 2024
575f8da
Merge branch 'main' into ss/top-boundary-condition
simone-silvestri Nov 23, 2024
f6f3dd1
indices in reductions
simone-silvestri Nov 23, 2024
621f1e6
Merge branch 'ss/top-boundary-condition' of github.com:CliMA/Oceanani…
simone-silvestri Nov 23, 2024
34dfe63
add a test
simone-silvestri Nov 23, 2024
7f7b86b
hmmm
simone-silvestri Nov 23, 2024
9add855
Merge branch 'main' into ss/top-boundary-condition
simone-silvestri Nov 27, 2024
929bc24
bugfix
simone-silvestri Nov 27, 2024
47b398f
another bugfix
simone-silvestri Nov 27, 2024
091c6cb
extending `view`s for operations
simone-silvestri Nov 27, 2024
6b0c234
should be ready to go
simone-silvestri Nov 27, 2024
9706ad6
sprinkle more OneTo around
simone-silvestri Nov 27, 2024
8c450e3
tests should pass
simone-silvestri Nov 27, 2024
8b75606
this works unfortunate we cannot use fields
simone-silvestri Nov 27, 2024
7c83f6b
revert what not needed
simone-silvestri Nov 27, 2024
8b3db85
stricter conditions
simone-silvestri Nov 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
11 changes: 11 additions & 0 deletions src/AbstractOperations/conditional_operations.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Oceananigans.Fields: OneField
using Oceananigans.Grids: architecture

using OffsetArrays

import Oceananigans.Architectures: on_architecture
import Oceananigans.Fields: condition_operand, conditional_length, set!, compute_at!, indices


# For conditional reductions such as mean(u * v, condition = u .> 0))
struct ConditionalOperation{LX, LY, LZ, O, F, G, C, M, T} <: AbstractOperation{LX, LY, LZ, G, T}
operand :: O
Expand Down Expand Up @@ -115,6 +118,14 @@ end
return ConditionalOperation(operand; func, condition, mask)
end

@inline function condition_operand(data::OffsetArray, grid::AbstractGrid, Loc::Tuple, condition, mask)
condition = on_architecture(architecture(grid), condition)
return ConditionalOperation{Loc...}(operand, identity, grid, condition, mask)
end

condition_operand(data::OffsetArray, grid::AbstractGrid, Loc::Tuple, ::Nothing, mask) =
condition_operand(data, grid, Loc, TrueCondition(), mask)

@inline condition_operand(func::typeof(identity), c::ConditionalOperation, ::Nothing, mask) = ConditionalOperation(c; mask)
@inline condition_operand(func::Function, c::ConditionalOperation, ::Nothing, mask) = ConditionalOperation(c; func, mask)

Expand Down
1 change: 1 addition & 0 deletions src/BoundaryConditions/BoundaryConditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ include("fill_halo_regions_nothing.jl")
include("apply_flux_bcs.jl")

include("update_boundary_conditions.jl")
include("polar_boundary_condition.jl")

include("flat_extrapolation_open_boundary_matching_scheme.jl")
end # module
19 changes: 13 additions & 6 deletions src/BoundaryConditions/field_boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ function regularize_immersed_boundary_condition(ibc, grid, loc, field_name, args
return NoFluxBoundaryCondition()
end

regularize_west_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_east_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_south_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_north_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_bottom_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_top_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)

# regularize default boundary conditions
function regularize_boundary_condition(default::DefaultBoundaryCondition, grid, loc, dim, args...)
default_bc = default_prognostic_bc(topology(grid, dim)(), loc[dim](), default)
Expand Down Expand Up @@ -212,12 +219,12 @@ function regularize_field_boundary_conditions(bcs::FieldBoundaryConditions,

loc = assumed_field_location(field_name)

west = regularize_boundary_condition(bcs.west, grid, loc, 1, LeftBoundary, prognostic_names)
east = regularize_boundary_condition(bcs.east, grid, loc, 1, RightBoundary, prognostic_names)
south = regularize_boundary_condition(bcs.south, grid, loc, 2, LeftBoundary, prognostic_names)
north = regularize_boundary_condition(bcs.north, grid, loc, 2, RightBoundary, prognostic_names)
bottom = regularize_boundary_condition(bcs.bottom, grid, loc, 3, LeftBoundary, prognostic_names)
top = regularize_boundary_condition(bcs.top, grid, loc, 3, RightBoundary, prognostic_names)
west = regularize_west_boundary_condition(bcs.west, grid, loc, 1, LeftBoundary, prognostic_names)
east = regularize_east_boundary_condition(bcs.east, grid, loc, 1, RightBoundary, prognostic_names)
south = regularize_south_boundary_condition(bcs.south, grid, loc, 2, LeftBoundary, prognostic_names)
north = regularize_north_boundary_condition(bcs.north, grid, loc, 2, RightBoundary, prognostic_names)
bottom = regularize_bottom_boundary_condition(bcs.bottom, grid, loc, 3, LeftBoundary, prognostic_names)
top = regularize_top_boundary_condition(bcs.top, grid, loc, 3, RightBoundary, prognostic_names)

immersed = regularize_immersed_boundary_condition(bcs.immersed, grid, loc, field_name, prognostic_names)

Expand Down
76 changes: 76 additions & 0 deletions src/BoundaryConditions/polar_boundary_condition.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const PolarBoundaryCondition{V} = BoundaryCondition{<:Value, <:PolarValue}

condition_operand(data, grid, Loc, condition, mask) = data

struct PolarValue{C}
c :: C
end

PolarBoundaryCondition(field) =
ValueBoundaryCondition(PolarValue(field))

@inline getbc(pv::PolarValue, args...) = getbc(pv.c, args...)

# TODO: vectors should have a different treatment since vector components should account for the frame of reference
# North - South flux boundary conditions are not valid on a Latitude-Longitude grid if the last / first rows represent the poles
function regularize_north_boundary_condition(bc::DefaultBoundaryCondition, grid::LatitudeLongitudeGrid, loc, dim, args...) where C
φmax = φnode(grid.Ny+1, grid, Face())

if φmax == 90
_, LY, LZ = loc
field = Field{Nothing, LY, LZ}(grid; indices = (:, grid.Ny, :))
return PolarBoundaryCondition(field)
else
return regularize_boundary_condition(bc, grid, args...)
end
end

# North - South flux boundary conditions are not valid on a Latitude-Longitude grid if the last / first rows represent the poles
function regularize_south_boundary_condition(bc::DefaultBoundaryCondition, grid::LatitudeLongitudeGrid, loc, dim, args...)
φmin = φnode(1, grid, Face())

if φmin == - 90
_, LY, LZ = loc
field = Field{Nothing, LY, LZ}(grid; indices = (:, 1, :))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does seem right

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But should LY actually be flipped? Eg this is Face for a Center location. (It may not matter)

Copy link
Collaborator Author

@simone-silvestri simone-silvestri Nov 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably you are right. I have found out unfortunately that reductions on windowed fields do not work. I ll try to make it work so here we can do

mean!(windowed_field, full_field)

return PolarBoundaryCondition(field)
else
return regularize_boundary_condition(bc, grid, args...)
end
end

function update_pole_value!(bc::PolarBoundaryCondition, c, grid, loc)
operand = condition_operand(c, grid, loc, nothing, 0)
mean!(bc.condition.c, operand)
return nothing
end

function fill_south_halo!(c, bc::PolarBoundaryCondition, size, offset, loc, arch, grid, args...; only_local_halos = false, kwargs...) =
update_pole_value!(bc, c, grid, loc)
return launch!(arch, grid, KernelParameters(size, offset),
_fill_only_south_halo!, c, bc, loc, grid, Tuple(args); kwargs...)
end

function fill_north_halo!(c, bc::PolarBoundaryCondition, size, offset, loc, arch, grid, args...; only_local_halos = false, kwargs...) =
update_pole_value!(bc, c, grid, loc)
return launch!(arch, grid, KernelParameters(size, offset),
_fill_only_north_halo!, c, bc, loc, grid, Tuple(args); kwargs...)
end

function fill_south_and_north_halo!(c, south_bc::PolarBoundaryCondition, north_bc, size, offset, loc, arch, grid, args...; only_local_halos = false, kwargs...)
update_pole_value!(south_bc, c, grid, loc)
return launch!(arch, grid, KernelParameters(size, offset),
_fill_south_and_north_halo!, c, south_bc, north_bc, loc, grid, Tuple(args); kwargs...)
end

function fill_south_and_north_halo!(c, south_bc, north_bc::PolarBoundaryCondition, size, offset, loc, arch, grid, args...; only_local_halos = false, kwargs...)
update_pole_value!(north_bc, c, grid, loc)
return launch!(arch, grid, KernelParameters(size, offset),
_fill_south_and_north_halo!, c, south_bc, north_bc, loc, grid, Tuple(args); kwargs...)
end

function fill_south_and_north_halo!(c, south_bc::PolarBoundaryCondition, north_bc::PolarBoundaryCondition, size, offset, loc, arch, grid, args...; only_local_halos = false, kwargs...)
update_pole_value!(south_bc, c, grid, loc)
update_pole_value!(north_bc, c, grid, loc)
return launch!(arch, grid, KernelParameters(size, offset),
_fill_south_and_north_halo!, c, south_bc, north_bc, loc, grid, Tuple(args); kwargs...)
end
1 change: 1 addition & 0 deletions src/BoundaryConditions/update_boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ function update_boundary_condition!(fields::Tuple, model)

return nothing
end

1 change: 1 addition & 0 deletions src/Fields/field.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ using Base: @propagate_inbounds
import Oceananigans: boundary_conditions
import Oceananigans.Architectures: on_architecture
import Oceananigans.BoundaryConditions: fill_halo_regions!, getbc
import Oceananigans.BoundaryConditions: condition_operand
import Statistics: norm, mean, mean!
import Base: ==

Expand Down
6 changes: 6 additions & 0 deletions src/ImmersedBoundaries/immersed_reductions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const IF = AbstractField{<:Any, <:Any, <:Any, <:ImmersedBoundaryGrid}
return ConditionalOperation(op; func, condition=ni_condition, mask)
end

@inline function condition_operand(data::OffsetArray, grid::AbstractGrid, Loc, condition, mask)
condition = on_architecture(architecture(grid), condition)
ni_condition = NotImmersed(condition)
return ConditionalOperation{Loc...}(operand, identity, grid, condition, mask)
end

@inline conditional_length(c::IF) = conditional_length(condition_operand(identity, c, nothing, 0))
@inline conditional_length(c::IF, dims) = conditional_length(condition_operand(identity, c, nothing, 0), dims)

Expand Down