Skip to content

Passive tracers are not conserved on tripolar grid if wind is blowing #4466

Open
@NoraLoose

Description

@NoraLoose

I noticed that passive tracers are not conserved in my global simulation (with a tripolar grid and the z-star coordinate) when a prescribed atmosphere is added (i.e., with JRA55 and ClimaOcean). I’ve been able to isolate the issue to an Oceananigans-only MWE, adapted from the tripolar grid tracer conservation test in our suite. The only change is the addition of wind forcing.

Below is the simplified test setup used to reproduce the issue:

function run_tripolar_test_simulation(arch; with_wind = false)

    z_stretched = MutableVerticalDiscretization(collect(-20:0))
    grid = TripolarGrid(arch; size = (20, 20, 20), z = z_stretched)

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

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

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

    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₁₀, cᴰ, ρₒ, ρₐ = 10.0, 2.5e-3, 1026.0, 1.225
        τx = -ρₐ / ρₒ * cᴰ * u₁₀ * abs(u₁₀)
        u_bcs = FieldBoundaryConditions(top = FluxBoundaryCondition(τx))
        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{Center, Center, Center}(grid)
    set!(ψ, rand(size(ψ)...))
    uᵢ = ∂y(ψ)
    vᵢ = -∂x(ψ)

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

    simulation = Simulation(model, Δt=2minutes, stop_time=1day)
    
    c = simulation.model.tracers.c
    tracer_integral = Integral(c, dims=(1, 2, 3))

    if with_wind
        prefix = "test_with_wind"
    else
        prefix = "test_no_wind"
    end
    
    integral_ow = JLD2Writer(
        simulation.model,
        (; tracer_integral),
        filename = "$(prefix)_integrals",
        schedule = IterationInterval(1),
        overwrite_existing = true,
    )
    simulation.output_writers[:integral] = integral_ow

    run!(simulation)
    
    return nothing
end

run_tripolar_test_simulation(GPU(); with_wind = false)
run_tripolar_test_simulation(GPU(); with_wind = true)

Visualizing the results shows that the passive tracer c is

  • conserved for the simulation without wind, which matches the behavior tested in our CI.
  • not conserved for the simulation with wind, despite all other settings being identical.

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions