Skip to content
Open
Changes from 1 commit
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
33 changes: 30 additions & 3 deletions src/Thermodynamics/reference_states.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using Oceananigans: Oceananigans, Center, Field, set!, fill_halo_regions!
using Oceananigans.Utils: launch!
using Oceananigans.Operators: Δzᶜᶜᶠ, ℑzᵃᵃᶠ

using Adapt: Adapt, adapt
using KernelAbstractions: @kernel, @index

#####
##### Reference state computations for Boussinesq and Anelastic models
Expand Down Expand Up @@ -91,12 +95,35 @@ function ReferenceState(grid, thermo=ThermodynamicConstants(eltype(grid));
p₀ = convert(FT, base_pressure)
θ₀ = convert(FT, potential_temperature)

pᵣ = Field{Nothing, Nothing, Center}(grid)
ρᵣ = Field{Nothing, Nothing, Center}(grid)
set!(pᵣ, z -> adiabatic_hydrostatic_pressure(z, p₀, θ₀, thermo))
set!(ρᵣ, z -> adiabatic_hydrostatic_density(z, p₀, θ₀, thermo))
fill_halo_regions!(pᵣ)
fill_halo_regions!(ρᵣ)

pᵣ = Field{Nothing, Nothing, Center}(grid)
compute_reference_pressure!(pᵣ, grid, p₀, ρᵣ, thermo)
# set!(pᵣ, z -> adiabatic_hydrostatic_pressure(z, p₀, θ₀, thermo))
fill_halo_regions!(pᵣ)

return ReferenceState(p₀, θ₀, pᵣ, ρᵣ)
end

@kernel function _compute_reference_pressure!(pᵣ, grid, p₀, ρᵣ, thermo)
i, j = @index(Global, NTuple)

# ∂z p = - ρᵣ g
# (p⁺ - pᵏ) / Δz = - ℑzᶠ(ρᵣ) * g
# p⁺ = pᵏ - ℑzᶠ(ρᵣ) * g Δz

@inbounds pᵣ[i, j, 1] = p₀
g = thermo.gravitational_acceleration

for k = 2:grid.Nz
@inbounds pᵣ[i, j, k] = pᵣ[i, j, k-1] - ℑzᵃᵃᶠ(i, j, k, grid, ρᵣ) * g * Δzᶜᶜᶠ(i, j, k, grid)
Copy link
Member

@navidcy navidcy Nov 21, 2025

Choose a reason for hiding this comment

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

are we sure it's not

... - ℑzᵃᵃᶠ(i, j, k-1, grid, ρᵣ) * g * Δzᶜᶜᶠ(i, j, k-1, grid)

?

Copy link
Member

Choose a reason for hiding this comment

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

We want to interpolate the density on the face between cell center k-1 and k and add it to the integral, right? But that's face k-1, no?

Copy link
Member

@navidcy navidcy Nov 21, 2025

Choose a reason for hiding this comment

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

using Oceananigans
using CairoMakie
using Oceananigans.Operators: Δzᶜᶜᶠ, ℑzᵃᵃᶠ

grid = RectilinearGrid(size=20, z=(0, 5), topology=(Flat, Flat, Bounded))

ρ = CenterField(grid)

p₁ = CenterField(grid)
p₂ = CenterField(grid)
p_analytic = CenterField(grid)

p₀ = 123.2

set!(ρ, z -> exp(-2z))

# dp/dz = - ρ, p(0) = p₀
set!(p_analytic, z -> p₀ + 1/2 * (exp(-2z) - 1))

for f in (p₁, p₂, p_analytic)
    f[1] = p₀
end

i, j = 1, 1
for k = 2:grid.Nz
    @inbounds p₁[i, j, k] = p₁[i, j, k-1] - ℑzᵃᵃᶠ(i, j, k, grid, ρ) * Δzᶜᶜᶠ(i, j, k, grid)
    @inbounds p₂[i, j, k] = p₂[i, j, k-1] - ℑzᵃᵃᶠ(i, j, k-1, grid, ρ) * Δzᶜᶜᶠ(i, j, k-1, grid)
end

fig = Figure()
axρ = Axis(fig[1, 1], ylabel="ρ(z)")
axp = Axis(fig[1, 2], ylabel="p(z)")
axe = Axis(fig[1, 3], ylabel="error")

lines!(axρ, ρ)

scatterlines!(axp, p₁)
scatterlines!(axp, p₂)
scatterlines!(axp, p_analytic)

scatterlines!(axe, abs(p_analytic - p₁), label="|p_analytic - p₁|")
scatterlines!(axe, abs(p_analytic - p₂), label="|p_analytic - p₂|")
axislegend(axe, position=:rt)

fig
display

Copy link
Member

@navidcy navidcy Nov 21, 2025

Choose a reason for hiding this comment

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

Not sure which is better; given that it's only derivatives of pressure that matter the blue might be better since it's more "parallel" to the analytic? If abs value matters, seems like yellow is better as it doesn't have that offset error...

Copy link
Member Author

Choose a reason for hiding this comment

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

oh you are right!

Copy link
Member Author

Choose a reason for hiding this comment

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

pretty nice demo btw

end
end

function compute_reference_pressure!(pᵣ, grid, p₀, ρᵣ, thermo)
arch = grid.architecture
launch!(arch, grid, (1, 1), _compute_reference_pressure!, pᵣ, grid, p₀, ρᵣ, thermo)
return nothing
end
Loading