Skip to content

Conversation

@simone-silvestri
Copy link
Collaborator

@simone-silvestri simone-silvestri commented Sep 23, 2025

This is a work-in-progress PR that aims to reformulate the timestepping scheme of the HydrostaticFreeSurfaceModel to
make sure that three numerical properties are satisfied:

  • tracers are globally conserved (the integral of a tracer field remains constant in the absence of forcings)
  • tracers are locally conserved (an initially constant tracer remains constant in the absence of forcings)
  • The free surface is evolved consistently with the grid thickness.

This is easier to achieve with an explicit discretization of the free surface (ExplicitFreeSurface and SplitExplicitFreeSurface) rather than an implicit free surface discretization and with RK3 rather than AB2.
However, this PR reformulates much of the timestepping algorithm, so it will be a lengthy WIP that will need to be thoroughly validated for all combinations of barotropic and baroclinic timestepping schemes.

More changes are performed to correctly abstract the timestepping schemes, which, at the moment, are tailored specifically to the NonhydrostaticModel (for example, the timesteppers include a compute_pressure_correction! or a correct_velocities function, which are meaningful only for a non-hydrostatic Navier Stokes solver)

Edit: another objective I have is to remove any timestepping from the update_state! function. We should be able to call update_state! multiple times in a row without problems and timestepping inside update_state! negates this possibility.

TODO:

  • Remove timestepping from update_state! In another PR
  • Clean up the time-stepping code
  • Introduce transport weights for transport averaging in the SplitExplicitFreeSurface
  • Implement a conservative, low-storage Runge Kutta method (of arbitrary order) using the Explicit free surface
  • Implement a conservative, low-storage Runge Kutta method (of arbitrary order) coupled with the SplitExplicitFreeSurface
  • Implement a conservative, low-storage Runge Kutta method (of arbitrary order) using the (PCG) ImplicitFreeSurface
  • Ensure that the conservation is satisfied on DistributedGrids
  • Implement a semi - conservative method for AB2 In another PR
  • Address precision errors that tend to destroy conservation for constant fields In another PR

Comment on lines +49 to +50
velocities :: U # Container for velocity fields `u`, `v`, and `w`
transport_velocities :: W # Container for velocity fields used to transport tracers
Copy link
Member

Choose a reason for hiding this comment

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

the difference between "normal velocities" and "transport velocities" is unclear

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, how should we call them? They are the velocities that transport tracers around. transport is not good because it implies a multiplication times the area...

@navidcy navidcy added the numerics 🧮 So things don't blow up and boil the lobsters alive label Sep 25, 2025
@simone-silvestri
Copy link
Collaborator Author

I am at the point here that the RK formulation is conservative both locally and globally.
However, there seems to be precision errors accumulating when the initial field is constant, which break conservation.
I have gotten some suggestions from @milankl as to how to tackle this issue. I will post a MWE later on when I have addressed some other points (conservation on distributed architectures and on AB2).

# Synchronize model state if needed
for field in fields(model)
synchronize_communication!(field)
end
Copy link
Member

Choose a reason for hiding this comment

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

how related to this PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am trying to figure out how to distribute operations in time. I don't think this is necessary anymore.

Comment on lines 55 to 61
# `Centered(order=12`) and `UpwindBiased(order=11)`. The list can be extended in order to
# `Centered(order=10`) and `UpwindBiased(order=9)`. The list can be extended in order to
# compile schemes with higher orders; for example `advection_buffers = [1, 2, 3, 4, 5, 6, 8]`
# will compile schemes for `advection_buffer=8` and thus `Centered(order=16)` and `UpwindBiased(order=15)`.
# Note that it is not possible to compile schemes for `advection_buffer = 41` or higher.
const advection_buffers = [1, 2, 3, 4, 5, 6]
const advection_buffers = [1, 2, 3, 4, 5]
Copy link
Member

Choose a reason for hiding this comment

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

why?

Copy link
Member

Choose a reason for hiding this comment

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

we should compile past the recommended order. If order=9 is recommended we need order=11 to verify this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay, I guess I'll take this suggestion for #4434, which, apart from this change, should be ready.

@glwagner
Copy link
Member

glwagner commented Oct 3, 2025

why are there so many changes to WENO advection, etc?

end

@inline function update_grid_scaling!(σᶜᶜⁿ, σᶠᶜⁿ, σᶜᶠⁿ, σᶠᶠⁿ, σᶜᶜ⁻, i, j, grid, ηⁿ)
@inline function update_grid_scaling!(z, i, j, grid)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@inline function update_grid_scaling!(z, i, j, grid)
@inline function update_grid_scaling!(z_coordinate, i, j, grid)

# First stage
#

compute_flux_bc_tendencies!(model)
Copy link
Member

Choose a reason for hiding this comment

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

how are they computed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tried putting this back inside the compute_tendencies! given that these cannot be computed in update_state! anymore. I will verify everything is consistent.

@glwagner
Copy link
Member

glwagner commented Oct 3, 2025

It's really hard for me to understand how this is an improvement. I think some explanation is needed (maybe docs or a docstring...)

@glwagner
Copy link
Member

glwagner commented Oct 3, 2025

It wouldn't be a completely crazy idea to start a new docs section on "Time steppers" which outlines how each time stepper works. Esp because there appears to be a kind of interface for using different methods, eg AB2 and RK3.

@simone-silvestri
Copy link
Collaborator Author

why are there so many changes to WENO advection, etc?

I have merged in #4434 because I was expecting to merge it before this one. Maybe that was a mistake

@simone-silvestri
Copy link
Collaborator Author

It wouldn't be a completely crazy idea to start a new docs section on "Time steppers" which outlines how each time stepper works. Esp because there appears to be a kind of interface for using different methods, eg AB2 and RK3.

Yeah that would be nice! After this PR we can also use RK for sea ice, for example, by extending rk_substep!

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

Labels

benchmark performance runs preconfigured benchamarks and spits out timing numerics 🧮 So things don't blow up and boil the lobsters alive

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants