Skip to content

[WIP] Fix tracer conservation when wind is blowing #4467

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
118 changes: 75 additions & 43 deletions test/test_zstar_coordinate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ end
@test all(um.data .≈ us.data)
end

# vertical z-levels for tracer conservation tests
z_stretched = MutableVerticalDiscretization(collect(-20:0))

@testset "ZStar tracer conservation testset" begin
z_stretched = MutableVerticalDiscretization(collect(-20:0))
topologies = ((Periodic, Periodic, Bounded),
(Periodic, Bounded, Bounded),
(Bounded, Periodic, Bounded),
Expand Down Expand Up @@ -234,55 +236,85 @@ end
Δt = 2minutes
test_zstar_coordinate(model, 100, Δt)
end

@testset "TripolarGrid ZStar tracer conservation tests" begin
@info "Testing a ZStar coordinate with a Tripolar grid on $(arch)..."

grid = TripolarGrid(arch; size = (20, 20, 20), z = z_stretched)

# Code credit:
# https://github.com/PRONTOLab/GB-25/blob/682106b8487f94da24a64d93e86d34d560f33ffc/src/model_utils.jl#L65
function mtn₁(λ, φ)
λ₁ = 70
φ₁ = 55
dφ = 5
return exp(-((λ - λ₁)^2 + (φ - φ₁)^2) / 2dφ^2)
end

function mtn₂(λ, φ)
λ₁ = 70
λ₂ = λ₁ + 180
φ₂ = 55
dφ = 5
return exp(-((λ - λ₂)^2 + (φ - φ₂)^2) / 2dφ^2)
end

zb = - 20
h = - zb + 10
gaussian_islands(λ, φ) = zb + h * (mtn₁(λ, φ) + mtn₂(λ, φ))
end
end

grid = ImmersedBoundaryGrid(grid, GridFittedBottom(gaussian_islands))
free_surface = SplitExplicitFreeSurface(grid; substeps=10)
function make_tripolar_test_model(arch; with_wind = false)

model = HydrostaticFreeSurfaceModel(; grid,
free_surface,
tracers = (:b, :c),
buoyancy = BuoyancyTracer(),
vertical_coordinate = ZStar())
grid = TripolarGrid(arch; size = (20, 20, 20), z = z_stretched)

bᵢ(x, y, z) = y < 0 ? 0.06 : 0.01
# Code credit:
# https://github.com/PRONTOLab/GB-25/blob/682106b8487f94da24a64d93e86d34d560f33ffc/src/model_utils.jl#L65
function mtn₁(λ, φ)
λ₁ = 70
φ₁ = 55
dφ = 5
return exp(-((λ - λ₁)^2 + (φ - φ₁)^2) / 2dφ^2)
end

# Instead of initializing with random velocities, infer them from a random initial streamfunction
# to ensure the velocity field is divergence-free at initialization.
ψ = Field{Center, Center, Center}(grid)
set!(ψ, rand(size(ψ)...))
uᵢ = ∂y(ψ)
vᵢ = -∂x(ψ)
function mtn₂(λ, φ)
λ₁ = 70
λ₂ = λ₁ + 180
φ₂ = 55
dφ = 5
return exp(-((λ - λ₂)^2 + (φ - φ₂)^2) / 2dφ^2)
end

set!(model, c = (x, y, z) -> rand(), u = uᵢ, v = vᵢ, b = bᵢ)
zb = - 20
h = - zb + 10
gaussian_islands(λ, φ) = zb + h * (mtn₁(λ, φ) + mtn₂(λ, φ))

Δt = 2minutes
test_zstar_coordinate(model, 300, Δt)
end
grid = ImmersedBoundaryGrid(grid, GridFittedBottom(gaussian_islands))
free_surface = SplitExplicitFreeSurface(grid; substeps=10)

kwargs = (;
grid,
free_surface,
tracers = (:b, :c),
buoyancy = BuoyancyTracer(),
vertical_coordinate = ZStar()
)

if with_wind
u_bcs = FieldBoundaryConditions(top = FluxBoundaryCondition(-1e-4))
model = HydrostaticFreeSurfaceModel(; kwargs..., boundary_conditions = (u = u_bcs,))
else
model = HydrostaticFreeSurfaceModel(; kwargs...)
end

bᵢ(x, y, z) = y < 0 ? 0.06 : 0.01

# Instead of initializing with random velocities, infer them from a random initial streamfunction
# to ensure the velocity field is divergence-free at initialization.
ψ = Field{Face, Face, Center}(grid)
set!(ψ, rand(size(ψ)...))
uᵢ = ∂y(ψ)
vᵢ = -∂x(ψ)

set!(model, c = (x, y, z) -> rand(), u = uᵢ, v = vᵢ, b = bᵢ)

return model
end

@testset "TripolarGrid ZStar tracer conservation tests" begin
for arch in archs
@info "Testing ZStar coordinate with TripolarGrid on $(arch)..."

model = make_tripolar_test_model(arch, with_wind=false)
Δt = 2minutes
test_zstar_coordinate(model, 300, Δt)
Comment on lines +305 to +307
Copy link
Member

Choose a reason for hiding this comment

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

is it possible to write this test to use any grid? or maybe too difficult?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Could be done with a slight refactor. Question is: Do we want to double the number of tests? We are testing quite a number of rectilinear grid cases (different topologies, immersed boundary vs. not, etc.)

Copy link
Collaborator Author

@NoraLoose NoraLoose May 2, 2025

Choose a reason for hiding this comment

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

It's probably worth doing the refactor and test with wind forcing for all grids. This would also answer the question whether the issue is specific to the TripolarGrid. I will continue working on this in a few hours.

Copy link
Member

@glwagner glwagner May 2, 2025

Choose a reason for hiding this comment

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

we can take a look at how long the test is taking and decide based on that perhaps. Perhaps prioritizing just lat-lon along with Tripolar makes sense

end
end

@testset "ZStar tracer conservation tests with wind stress" begin
for arch in archs
@info "Testing ZStar coordinate with TripolarGrid and wind stress on $(arch)..."

model = make_tripolar_test_model(arch; with_wind=true)
Δt = 2minutes
test_zstar_coordinate(model, 300, Δt)
end
end