Skip to content

(0.96.33) Correct diffusion with a non-linear free surface #4589

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

simone-silvestri
Copy link
Collaborator

@simone-silvestri simone-silvestri commented Jun 9, 2025

PR #4546 changed the implementation of zstar and a nonlinear free surface. In particular, before #4546 we were

    1. updating σT
    1. performing implicit diffusion on σT
    1. advancing σ
    1. diagnosing T at the new timestep

PR#4546 changed this in

    1. updating σ
    1. computing directly T from updating σT and dividing by the new σ
    1. implicit diffusion

After #4546, the diffusion is performed on T and not σT, but #4546 did not update the vertically implicit diffusion solver (I also think there was a bug before), for this reason, the non linear free surface solution is way more diffusive now than the same solution with a static grid. This leads to SST increasing drastically using zstar compared to using a static vertical coordinate in ClimaOcean.

This PR corrects the formulation and adds a very simple test, where if the free surface does not change, the results should be the same for static and moving grid (H+η)_moving == H_static.
If we run same test I added in this PR on main:

z_static = [i + rand() for i in -15:0]
z_static[1] = -15
z_static[end] = 0
z_moving = MutableVerticalDiscretization(z_static ./ 1.5)
    
c₀ = rand(15)

grid_static = RectilinearGrid(size=15, z=z_static, topology=(Flat, Flat, Bounded))
grid_moving = RectilinearGrid(size=15, z=z_moving, topology=(Flat, Flat, Bounded))

fill!(grid_moving.z.ηⁿ,   5)
fill!(grid_moving.z.σᶜᶜ⁻, 1.5)
fill!(grid_moving.z.σᶜᶜⁿ, 1.5)
fill!(grid_moving.z.σᶜᶠⁿ, 1.5)
fill!(grid_moving.z.σᶠᶠⁿ, 1.5)
fill!(grid_moving.z.σᶠᶜⁿ, 1.5)

model_static = HydrostaticFreeSurfaceModel(; grid = grid_static, 
                                            tracers = :c,
                                            closure = VerticalScalarDiffusivity(VerticallyImplicitTimeDiscretization(), κ=0.1))
                                                
model_moving = HydrostaticFreeSurfaceModel(; grid = grid_moving, 
                                            tracers = :c,
                                            closure = VerticalScalarDiffusivity(VerticallyImplicitTimeDiscretization(), κ=0.1))
                                        
set!(model_static, c = c₀)
set!(model_moving, c = c₀)

for _ in 1:1000
    time_step!(model_static, 1.0)
    time_step!(model_moving, 1.0)
end

lines(interior(model_static.tracers.c, 1, 1, :), label="Static Grid")
lines!(interior(model_moving.tracers.c, 1, 1, :), label="Moving Grid", linestyle=:dash)
axislegend()

we get

on main

image

on this PR

image

The detailed formulation of the equations we solve is begin added in #4588

@simone-silvestri simone-silvestri requested a review from glwagner June 9, 2025 11:43
@simone-silvestri simone-silvestri changed the title Correct diffusion with a non-linear free surface (0.96.32) Correct diffusion with a non-linear free surface Jun 9, 2025
@simone-silvestri simone-silvestri requested a review from navidcy June 9, 2025 11:50
@francispoulin
Copy link
Collaborator

Very nice PR @simone-silvestri . Why is it that the curve changes from increasing to decreasing on this PR? I thought that the static grid before was correct, but now we are getting different tendencies.

Also, are the equations that describe this written down anywhere?

@simone-silvestri
Copy link
Collaborator Author

simone-silvestri commented Jun 9, 2025

Sorry, it's a consequence of the rand() at the beginning. I am writing down the equations in #4588, I ll start writing everything down tomorrow, with the objective of finishing this week.

@francispoulin
Copy link
Collaborator

Thanks @simone-silvestri !

@simone-silvestri simone-silvestri changed the title (0.96.32) Correct diffusion with a non-linear free surface (0.96.33) Correct diffusion with a non-linear free surface Jun 9, 2025
@navidcy
Copy link
Member

navidcy commented Jun 9, 2025

Clarifying question: what is σ and σT? (or are these going to be explained in #4588; shall I look there?)

end

params_range(H, N, ::Type{Flat}) = 1:1
params_range(H, N, T) = -H+2:N+H-1
Copy link
Member

Choose a reason for hiding this comment

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

is there any way we can get away from this *_params design? It doesn't scale because we have to add *_params for every single addition to the model, getting messy and requiring a lot of remembering the names and places of functions

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You prefer having a type that controls the parameters rather than a function?


@inline rcp_vertical_spacing(i, j, k, grid, ℓx, ℓy, ℓz) = Δz⁻¹(i, j, k, grid, ℓx, ℓy, ℓz)
@inline rcp_vertical_spacing(i, j, k, grid, ::Center, ::Center, ℓz) = Δr⁻¹(i, j, k, grid, c, c, ℓz)

Copy link
Member

Choose a reason for hiding this comment

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

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants