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

Different advection schemes in different directions #3732

Merged
merged 89 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
ea309b7
should be done
simone-silvestri Aug 26, 2024
83f870e
add the dicussion
simone-silvestri Aug 26, 2024
ad1ae41
disambiguation
simone-silvestri Aug 26, 2024
7843e0d
remove repeat code
simone-silvestri Aug 26, 2024
abecb28
precopmiles
simone-silvestri Aug 26, 2024
9d87f01
keep these changes for later
simone-silvestri Aug 26, 2024
03b0d28
correct the outside buffer
simone-silvestri Aug 26, 2024
6a15de8
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Aug 26, 2024
70d6475
fix tests
simone-silvestri Aug 26, 2024
5b75542
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Aug 26, 2024
42b1f3a
change the show method
simone-silvestri Aug 26, 2024
6181e01
back to previous buffer scheme
simone-silvestri Aug 26, 2024
77873b3
allow for changes in the advection
simone-silvestri Aug 26, 2024
9c7ff37
switch position of functions
simone-silvestri Aug 26, 2024
9ca656e
better comment
simone-silvestri Aug 26, 2024
4aabf62
better info
simone-silvestri Aug 26, 2024
39a4ef8
bugfix
simone-silvestri Aug 26, 2024
0ba24d6
better info
simone-silvestri Aug 26, 2024
71dbde1
make sure N==1 -> nothing
simone-silvestri Aug 26, 2024
817d058
Update src/Advection/momentum_advection_operators.jl
simone-silvestri Aug 26, 2024
11355d6
add topologies
simone-silvestri Aug 26, 2024
bc212e3
add topology argument
simone-silvestri Aug 26, 2024
680251d
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Aug 26, 2024
d0d40be
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Aug 26, 2024
261a31a
better adaptation
simone-silvestri Aug 26, 2024
cb7b090
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Aug 26, 2024
bcdb2c6
formatting
simone-silvestri Aug 26, 2024
d73b3d9
whoops
simone-silvestri Aug 26, 2024
d46eb4c
remove topology and less metaprogramming
simone-silvestri Aug 26, 2024
1b028f3
add advection
simone-silvestri Aug 26, 2024
9456881
dont adapt nothing
simone-silvestri Aug 26, 2024
3bc14be
retain same behavior as before
simone-silvestri Aug 27, 2024
ce30f43
fix multi region advection
simone-silvestri Aug 27, 2024
cd96911
bugfix scalar diffusivities parameter types
simone-silvestri Aug 27, 2024
7191393
bugfix
simone-silvestri Aug 27, 2024
e6a489c
enzyme error
simone-silvestri Aug 27, 2024
1a59a2d
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Aug 28, 2024
3313d7c
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Aug 29, 2024
2ce1537
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 4, 2024
e041ea6
make sure constructors are type-stable...
simone-silvestri Sep 4, 2024
a948955
force required_halo_size to be an integer
simone-silvestri Sep 4, 2024
1ffe239
add better comment
simone-silvestri Sep 4, 2024
39407f6
add a couple of unit tests
simone-silvestri Sep 4, 2024
b4f9e0f
test biharmonic diffusivity
simone-silvestri Sep 4, 2024
4811293
fix enzyme tests
simone-silvestri Sep 4, 2024
2e02dfe
correct adaptbetter explanation
simone-silvestri Sep 4, 2024
4a45a95
add a test for adapt_advection
simone-silvestri Sep 4, 2024
2e33b56
whoops wrong test
simone-silvestri Sep 4, 2024
ca876fa
revert changes
simone-silvestri Sep 4, 2024
b3a94d8
add couple more tests
simone-silvestri Sep 4, 2024
e1085a4
fix tests
simone-silvestri Sep 4, 2024
4a78168
without the extra space
simone-silvestri Sep 4, 2024
f5b7789
fix enzyme test
simone-silvestri Sep 4, 2024
98abf58
fix enzyme tests
simone-silvestri Sep 4, 2024
9f35ebe
fix nonhydrostatic tests
simone-silvestri Sep 4, 2024
cc98d5e
rmove one newline
simone-silvestri Sep 4, 2024
ab0827e
simplify test
simone-silvestri Sep 4, 2024
2eaf51e
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 6, 2024
9c2103a
Update src/Models/HydrostaticFreeSurfaceModels/hydrostatic_free_surfa…
simone-silvestri Sep 6, 2024
4b9aa61
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 6, 2024
2da6007
remove extra dispatches
simone-silvestri Sep 6, 2024
9f27dc3
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Sep 6, 2024
a91ca1c
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 9, 2024
4bed3f7
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 16, 2024
da88f62
relaunch the tests
simone-silvestri Sep 17, 2024
aa3d2cd
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 17, 2024
4cc6dfb
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 24, 2024
21015bb
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Sep 25, 2024
a50157f
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Oct 7, 2024
82d5ba7
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Oct 8, 2024
0d2e7bb
change comment
simone-silvestri Oct 8, 2024
c5709dd
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Oct 8, 2024
b6d65e2
switch to B
simone-silvestri Oct 8, 2024
1479884
new syntax for KernelParameters
simone-silvestri Oct 8, 2024
e741ce8
bugfix
simone-silvestri Oct 8, 2024
b03dc9d
another bugfix
simone-silvestri Oct 8, 2024
7cc9149
make sure the range is correct
simone-silvestri Oct 8, 2024
d09f8aa
Merge branch 'main' into ss/different-advection-scheme
simone-silvestri Oct 9, 2024
c909344
Update src/Advection/adapt_advection_order.jl
simone-silvestri Oct 9, 2024
5869952
Update src/Advection/adapt_advection_order.jl
simone-silvestri Oct 9, 2024
13c21aa
Update src/Advection/adapt_advection_order.jl
simone-silvestri Oct 9, 2024
96c5eda
remove comments
simone-silvestri Oct 9, 2024
d148896
Merge branch 'ss/different-advection-scheme' of github.com:CliMA/Ocea…
simone-silvestri Oct 9, 2024
da68014
this should be type stable for the moment
simone-silvestri Oct 9, 2024
9f3fffc
bugfix
simone-silvestri Oct 10, 2024
8bbaf03
bugfix
simone-silvestri Oct 10, 2024
402d031
better comment
simone-silvestri Oct 10, 2024
40e5dfa
fix the docs
simone-silvestri Oct 11, 2024
9214110
whoops
simone-silvestri Oct 11, 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: 8 additions & 3 deletions src/Advection/Advection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export
UpwindBiased, UpwindBiasedFirstOrder, UpwindBiasedThirdOrder, UpwindBiasedFifthOrder,
WENO, WENOThirdOrder, WENOFifthOrder,
VectorInvariant, WENOVectorInvariant,
TracerAdvection,
FluxFormAdvection,
EnergyConserving,
EnstrophyConserving

Expand All @@ -38,7 +38,7 @@ using Oceananigans.Architectures: architecture, CPU
using Oceananigans.Operators

import Base: show, summary
import Oceananigans.Grids: required_halo_size
import Oceananigans.Grids: required_halo_size_x, required_halo_size_y, required_halo_size_z
import Oceananigans.Architectures: on_architecture

abstract type AbstractAdvectionScheme{B, FT} end
Expand All @@ -55,9 +55,12 @@ abstract type AbstractUpwindBiasedAdvectionScheme{B, FT} <: AbstractAdvectionSch
# Note that it is not possible to compile schemes for `advection_buffer = 41` or higher.
const advection_buffers = [1, 2, 3, 4, 5, 6]

@inline required_halo_size(::AbstractAdvectionScheme{B}) where B = B
@inline Base.eltype(::AbstractAdvectionScheme{<:Any, FT}) where FT = FT

@inline required_halo_size_x(::AbstractAdvectionScheme{B}) where B = B
@inline required_halo_size_y(::AbstractAdvectionScheme{B}) where B = B
@inline required_halo_size_z(::AbstractAdvectionScheme{B}) where B = B

include("centered_advective_fluxes.jl")
include("upwind_biased_advective_fluxes.jl")

Expand All @@ -72,12 +75,14 @@ include("vector_invariant_upwinding.jl")
include("vector_invariant_advection.jl")
include("vector_invariant_self_upwinding.jl")
include("vector_invariant_cross_upwinding.jl")
include("flux_form_advection.jl")

include("flat_advective_fluxes.jl")
include("topologically_conditional_interpolation.jl")
include("momentum_advection_operators.jl")
include("tracer_advection_operators.jl")
include("positivity_preserving_tracer_advection_operators.jl")
include("cell_advection_timescale.jl")
include("adapt_advection_order.jl")

end # module
120 changes: 120 additions & 0 deletions src/Advection/adapt_advection_order.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@


function adapt_advection_order_x(advection::Centered{H}, grid::AbstractGrid, N::Int) where H
if N == 1
return nothing
elseif N >= H
return advection
else
return Centered(; order = N)
end
end

function adapt_advection_order_x(advection::UpwindBiased{H}, grid::AbstractGrid, N::Int) where H
if N == 1
return nothing
elseif N >= H
return advection
else
return UpwindBiased(; order = N)
end
end

adapt_advection_order_y(advection, grid::AbstractGrid, N::Int) = adapt_advection_order_x(advection, grid, N)
adapt_advection_order_z(advection, grid::AbstractGrid, N::Int) = adapt_advection_order_x(advection, grid, N)

"""
new_weno_scheme(grid, order, bounds, T)

Constructs a new WENO scheme based on the given parameters. `T` is the type of the weno coefficients.
A _non-stretched_ WENO scheme has `T` equal to `Nothing`. In case of a non-stretched WENO scheme,
we rebuild the advection without passing the grid information, otherwise we use the grid to account for stretched directions.
"""
new_weno_scheme(grid, order, bounds, T) = ifelse(T == Nothing, WENO(; order, bounds), WENO(grid; order, bounds))

function adapt_advection_order_x(advection::WENO{H, FT, XT, YT, ZT}, grid::AbstractGrid) where {H, FT, XT, YT, ZT}

if N == 1
return nothing
elseif N >= H
return advection
else
return new_weno_scheme(grid, N, advection.bounds, XT)
end
end

function adapt_advection_order_y(advection::WENO{H, FT, XT, YT, ZT}, grid::AbstractGrid, N::Int) where {H, FT, XT, YT, ZT}

if N > H
return advection
else
return new_weno_scheme(grid, N, advection.bounds, YT)
end
end

function adapt_advection_order_z(advection::WENO{H, FT, XT, YT, ZT}, grid::AbstractGrid, N::Int) where {H, FT, XT, YT, ZT}

if N == 1
return nothing
elseif N >= H
return advection
else
return new_weno_scheme(grid, N, advection.bounds, XT)
end
end

"""
adapt_advection_order(advection, grid::AbstractGrid)
Copy link
Member

Choose a reason for hiding this comment

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

This could just be validate_advection_scheme(scheme, grid). We often refer to this kind of thing as a "validation"

Copy link
Collaborator Author

@simone-silvestri simone-silvestri Oct 9, 2024

Choose a reason for hiding this comment

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

I tend to think of a validation as a non-returning function, I think that is how we use it


Adapts the advection operator `advection` based on the grid `grid` by adjusting the order of advection in each direction.
For example, if the grid has only one point in the x-direction, the advection operator in the x-direction is set to `nothing`.
A high order advection sheme is reduced to a lower order advection scheme if the grid has fewer points in that direction.

# Arguments
- `advection`: The original advection scheme.
- `grid::AbstractGrid`: The grid on which the advection scheme is applied.

The adapted advection scheme with adjusted advection order returned by this function is a `FluxFormAdvection`.
"""
function adapt_advection_order(advection, grid::AbstractGrid)
advection_x = adapt_advection_order_x(advection, grid, grid.Nx)
advection_y = adapt_advection_order_y(advection, grid, grid.Ny)
advection_z = adapt_advection_order_z(advection, grid, grid.Nz)

# Check that we indeed changed the advection operator
changed_x = advection_x != advection
changed_y = advection_y != advection
changed_z = advection_z != advection

new_advection = FluxFormAdvection(advection_x, advection_y, advection_z)
changed_advection = any((changed_x, changed_y, changed_z))

if changed_advection
@info "User-defined advection scheme $(advection) reduced to $(new_advection) to comply with grid-size limitations."
end

return ifelse(changed_advection, new_advection, advection)
end

function adapt_advection_order(advection::FluxFormAdvection, grid::AbstractGrid)
advection_x = adapt_advection_order_x(advection.x, grid, grid.Nx)
advection_y = adapt_advection_order_y(advection.y, grid, grid.Ny)
advection_z = adapt_advection_order_z(advection.z, grid, grid.Nz)

# Check that we indeed changed the advection operator
changed_x = advection_x != advection.x
changed_y = advection_y != advection.y
changed_z = advection_z != advection.z

new_advection = FluxFormAdvection(advection_x, advection_y, advection_z)
changed_advection = any((changed_x, changed_y, changed_z))

if changed_advection
@info "User-defined advection scheme $(advection) reduced to $(new_advection) to comply with grid-size limitations."
end

return ifelse(changed_advection, new_advection, advection)
end

# For the moment, we do not adapt the advection order for the VectorInvariant advection scheme
adapt_advection_order(advection::VectorInvariant, grid::AbstractGrid) = advection
58 changes: 58 additions & 0 deletions src/Advection/flux_form_advection.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Oceananigans.Operators: Vᶜᶜᶜ
using Oceananigans.Fields: ZeroField

struct FluxFormAdvection{N, FT, A, B, C} <: AbstractAdvectionScheme{N, FT}
x :: A
y :: B
z :: C

FluxFormAdvection{N, FT}(x::A, y::B, z::C) where {N, FT, A, B, C} = new{N, FT, A, B, C}(x, y, z)
end

"""
function FluxFormAdvection(x, y, z)

Builds a `FluxFormAdvection` type with reconstructions schemes `x`, `y`, and `z` to be applied in
the x, y, and z direction, respectively.
"""
function FluxFormAdvection(x_advection, y_advection, z_advection)
Hx = required_halo_size_x(x_advection)
Hy = required_halo_size_y(y_advection)
Hz = required_halo_size_z(z_advection)

FT = eltype(x_advection)
H = max(Hx, Hy, Hz)

return FluxFormAdvection{H, FT}(x_advection, y_advection, z_advection)
end

Base.show(io::IO, scheme::FluxFormAdvection) =
print(io, "FluxFormAdvection with reconstructions: ", " \n",
" ├── x: ", summary(scheme.x), "\n",
" ├── y: ", summary(scheme.y), "\n",
" └── z: ", summary(scheme.z))

@inline required_halo_size_x(scheme::FluxFormAdvection) = required_halo_size_x(scheme.x)
@inline required_halo_size_y(scheme::FluxFormAdvection) = required_halo_size_y(scheme.y)
@inline required_halo_size_z(scheme::FluxFormAdvection) = required_halo_size_z(scheme.z)

Adapt.adapt_structure(to, scheme::FluxFormAdvection{N, FT}) where {N, FT} =
FluxFormAdvection{N, FT}(Adapt.adapt(to, scheme.x),
Adapt.adapt(to, scheme.y),
Adapt.adapt(to, scheme.z))

@inline _advective_tracer_flux_x(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_tracer_flux_x(i, j, k, grid, advection.x, args...)
@inline _advective_tracer_flux_y(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_tracer_flux_y(i, j, k, grid, advection.y, args...)
@inline _advective_tracer_flux_z(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_tracer_flux_z(i, j, k, grid, advection.z, args...)

@inline _advective_momentum_flux_Uu(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Uu(i, j, k, grid, advection.x, args...)
@inline _advective_momentum_flux_Vu(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Vu(i, j, k, grid, advection.y, args...)
@inline _advective_momentum_flux_Wu(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Wu(i, j, k, grid, advection.z, args...)

@inline _advective_momentum_flux_Uv(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Uv(i, j, k, grid, advection.x, args...)
@inline _advective_momentum_flux_Vv(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Vv(i, j, k, grid, advection.y, args...)
@inline _advective_momentum_flux_Wv(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Wv(i, j, k, grid, advection.z, args...)

@inline _advective_momentum_flux_Uw(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Uw(i, j, k, grid, advection.x, args...)
@inline _advective_momentum_flux_Vw(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Vw(i, j, k, grid, advection.y, args...)
@inline _advective_momentum_flux_Ww(i, j, k, grid, advection::FluxFormAdvection, args...) = _advective_momentum_flux_Ww(i, j, k, grid, advection.z, args...)
17 changes: 17 additions & 0 deletions src/Advection/momentum_advection_operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,20 @@ which ends up at the location `ccf`.
δyᵃᶜᵃ(i, j, k, grid, _advective_momentum_flux_Vw, advection, U[2], w) +
δzᵃᵃᶠ(i, j, k, grid, _advective_momentum_flux_Ww, advection, U[3], w))
end

#####
##### Fallback advection fluxes!
#####

for flux_dir in (:Uu, :Vu, :Wu, :Uv, :Vv, :Wv, :Uw, :Vw, :Ww)
advective_momentum_flux = Symbol(:_advective_momentum_flux_, flux_dir)

@eval begin
@inline $advective_momentum_flux(i, j, k, grid, ::Nothing, args...) = zero(grid)
@inline $advective_momentum_flux(i, j, k, grid, ::Nothing, ::ZeroField, ::ZeroField) = zero(grid)
@inline $advective_momentum_flux(i, j, k, grid, ::Nothing, U, ::ZeroField) = zero(grid)
@inline $advective_momentum_flux(i, j, k, grid, scheme, ::ZeroField, ::ZeroField) = zero(grid)
@inline $advective_momentum_flux(i, j, k, grid, scheme, U, ::ZeroField) = zero(grid)
@inline $advective_momentum_flux(i, j, k, grid, scheme, ::ZeroField, u) = zero(grid)
end
end
27 changes: 18 additions & 9 deletions src/Advection/topologically_conditional_interpolation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,23 @@ const AUGXYZ = AUG{<:Any, <:Bounded, <:Bounded, <:Bounded}
# Left-biased buffers are smaller by one grid point on the right side; vice versa for right-biased buffers
# Center interpolation stencil look at i + 1 (i.e., require one less point on the left)

@inline outside_symmetric_haloᶠ(i, N, adv) = (i >= required_halo_size(adv) + 1) & (i <= N + 1 - required_halo_size(adv))
@inline outside_symmetric_haloᶜ(i, N, adv) = (i >= required_halo_size(adv)) & (i <= N + 1 - required_halo_size(adv))

@inline outside_biased_haloᶠ(i, N, adv) = (i >= required_halo_size(adv) + 1) & (i <= N + 1 - (required_halo_size(adv) - 1)) & # Left bias
(i >= required_halo_size(adv)) & (i <= N + 1 - required_halo_size(adv)) # Right bias
@inline outside_biased_haloᶜ(i, N, adv) = (i >= required_halo_size(adv)) & (i <= N + 1 - (required_halo_size(adv) - 1)) & # Left bias
(i >= required_halo_size(adv) - 1) & (i <= N + 1 - required_halo_size(adv)) # Right bias

for dir in (:x, :y, :z)
outside_symmetric_haloᶠ = Symbol(:outside_symmetric_halo_, dir, :ᶠ)
outside_symmetric_haloᶜ = Symbol(:outside_symmetric_halo_, dir, :ᶜ)
outside_biased_haloᶠ = Symbol(:outside_biased_halo_, dir, :ᶠ)
outside_biased_haloᶜ = Symbol(:outside_biased_halo_, dir, :ᶜ)
required_halo_size = Symbol(:required_halo_size_, dir)

@eval begin
@inline $outside_symmetric_haloᶠ(i, N, adv) = (i >= $required_halo_size(adv) + 1) & (i <= N + 1 - $required_halo_size(adv))
@inline $outside_symmetric_haloᶜ(i, N, adv) = (i >= $required_halo_size(adv)) & (i <= N + 1 - $required_halo_size(adv))

@inline $outside_biased_haloᶠ(i, N, adv) = (i >= $required_halo_size(adv) + 1) & (i <= N + 1 - ($required_halo_size(adv) - 1)) & # Left bias
(i >= $required_halo_size(adv)) & (i <= N + 1 - $required_halo_size(adv)) # Right bias
@inline $outside_biased_haloᶜ(i, N, adv) = (i >= $required_halo_size(adv)) & (i <= N + 1 - ($required_halo_size(adv) - 1)) & # Left bias
(i >= $required_halo_size(adv) - 1) & (i <= N + 1 - $required_halo_size(adv)) # Right bias
end
end
# Separate High order advection from low order advection
const HOADV = Union{WENO,
Tuple(Centered{N} for N in advection_buffers[2:end])...,
Expand Down Expand Up @@ -61,7 +70,7 @@ for bias in (:symmetric, :biased)
@eval @inline $alt1_interp(i, j, k, grid::$GridType, scheme::LOADV, args...) = $interp(i, j, k, grid, scheme, args...)
end

outside_buffer = Symbol(:outside_, bias, :_halo, loc)
outside_buffer = Symbol(:outside_, bias, :_halo_, ξ, loc)

# Conditional high-order interpolation in Bounded directions
if ξ == :x
Expand Down
86 changes: 15 additions & 71 deletions src/Advection/tracer_advection_operators.jl
Original file line number Diff line number Diff line change
@@ -1,80 +1,24 @@
using Oceananigans.Operators: Vᶜᶜᶜ
using Oceananigans.Fields: ZeroField

struct TracerAdvection{N, FT, A, B, C} <: AbstractAdvectionScheme{N, FT}
x :: A
y :: B
z :: C

TracerAdvection{N, FT}(x::A, y::B, z::C) where {N, FT, A, B, C} = new{N, FT, A, B, C}(x, y, z)
end

"""
function TracerAdvection(x, y, z)

Builds a `TracerAdvection` type with reconstructions schemes `x`, `y`, and `z` to be applied in
the x, y, and z direction, respectively.
"""
function TracerAdvection(x_advection, y_advection, z_advection)
Hx = required_halo_size(x_advection)
Hy = required_halo_size(y_advection)
Hz = required_halo_size(z_advection)

FT = eltype(x_advection)
H = max(Hx, Hy, Hz)

return TracerAdvection{H, FT}(x_advection, y_advection, z_advection)
end

Adapt.adapt_structure(to, scheme::TracerAdvection{N, FT}) where {N, FT} =
TracerAdvection{N, FT}(Adapt.adapt(to, scheme.x),
Adapt.adapt(to, scheme.y),
Adapt.adapt(to, scheme.z))

@inline _advective_tracer_flux_x(args...) = advective_tracer_flux_x(args...)
@inline _advective_tracer_flux_y(args...) = advective_tracer_flux_y(args...)
@inline _advective_tracer_flux_z(args...) = advective_tracer_flux_z(args...)

@inline _advective_tracer_flux_x(i, j, k, grid, advection::TracerAdvection, args...) =
_advective_tracer_flux_x(i, j, k, grid, advection.x, args...)

@inline _advective_tracer_flux_y(i, j, k, grid, advection::TracerAdvection, args...) =
_advective_tracer_flux_y(i, j, k, grid, advection.y, args...)

@inline _advective_tracer_flux_z(i, j, k, grid, advection::TracerAdvection, args...) =
_advective_tracer_flux_z(i, j, k, grid, advection.z, args...)

# Fallback for `nothing` advection
@inline _advective_tracer_flux_x(i, j, k, grid, ::Nothing, args...) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, ::Nothing, args...) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, ::Nothing, args...) = zero(grid)

# Fallback for `nothing` advection and `ZeroField` tracers and velocities
@inline _advective_tracer_flux_x(i, j, k, grid, ::Nothing, ::ZeroField, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, ::Nothing, ::ZeroField, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, ::Nothing, ::ZeroField, ::ZeroField) = zero(grid)

@inline _advective_tracer_flux_x(i, j, k, grid, ::Nothing, U, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, ::Nothing, V, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, ::Nothing, W, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_x(i, j, k, grid, ::Nothing, ::ZeroField, c) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, ::Nothing, ::ZeroField, c) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, ::Nothing, ::ZeroField, c) = zero(grid)

# Fallback for `ZeroField` tracers and velocities
@inline _advective_tracer_flux_x(i, j, k, grid, scheme, ::ZeroField, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, scheme, ::ZeroField, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, scheme, ::ZeroField, ::ZeroField) = zero(grid)

# Fallback for `ZeroField` tracers
@inline _advective_tracer_flux_x(i, j, k, grid, scheme, U, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, scheme, V, ::ZeroField) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, scheme, W, ::ZeroField) = zero(grid)
#####
##### Fallback tracer fluxes!
#####

# Fallback for `ZeroField` velocities
@inline _advective_tracer_flux_x(i, j, k, grid, scheme, ::ZeroField, c) = zero(grid)
@inline _advective_tracer_flux_y(i, j, k, grid, scheme, ::ZeroField, c) = zero(grid)
@inline _advective_tracer_flux_z(i, j, k, grid, scheme, ::ZeroField, c) = zero(grid)
for flux_dir in (:x, :y, :z)
advective_tracer_flux = Symbol(:_advective_tracer_flux_, flux_dir)

@eval begin
@inline $advective_tracer_flux(i, j, k, grid, ::Nothing, args...) = zero(grid)
@inline $advective_tracer_flux(i, j, k, grid, ::Nothing, ::ZeroField, ::ZeroField) = zero(grid)
@inline $advective_tracer_flux(i, j, k, grid, ::Nothing, U, ::ZeroField) = zero(grid)
@inline $advective_tracer_flux(i, j, k, grid, scheme, ::ZeroField, ::ZeroField) = zero(grid)
@inline $advective_tracer_flux(i, j, k, grid, scheme, U, ::ZeroField) = zero(grid)
@inline $advective_tracer_flux(i, j, k, grid, scheme, ::ZeroField, c) = zero(grid)
end
end
Copy link
Member

Choose a reason for hiding this comment

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

I preferred it as it was before without metaprogramming


#####
##### Tracer advection operator
Expand Down
Loading