Implement horizontal derivatives at constant z for MutableVerticalDiscretization#5101
Implement horizontal derivatives at constant z for MutableVerticalDiscretization#5101
MutableVerticalDiscretization#5101Conversation
MutableVerticalDiscretization
|
looks, good, make sure that these horizontal derivatives are not used anywhere in the dynamics where there are not intended to, and that this will work for fields that do not depend on z like the free surface (I think with this formulation will probably fail with an out-of-bounds error) |
|
Probably we need to define two-dimensional derivatives |
if there is anywhere in the dynamics that uses dx at constant r, doesn't that mean that those are currently incorrect for z* vertical coordinate? For example, with this definition there is no "additional" term needed to compute the horizontal pressure gradient. I expect the same is true for any gradient. |
for z-reduced fields, the operators like I think defining the reduced derivatives is probably out of scope for this PR. In practice, the third location in a horizontal derivative of a z-reduced field is ignored. |
|
I think this is not always the case, because we should do the same with the time derivative, aka we need the time derivative at constant r, not at constant z (we are time stepping in r-coordinate), which would be a bit inconvenient to express without some simplifications in the material derivatives to compensate. The dx at constant r are there because they elide with the chain rule for the time derivative. I think it is well documented here, see for example the derivations between equation 11 and 13 (the equivalent for momentum is 17 to 19). The pressure gradient (20)-(21) is a simple term that does not simplify, so the extra term remains hanging and for this reason we can use the chain rule. Also the vertical velocity (8) is not the same quantity in r-coordinate and z-coordinate, which implies other simplifications. |
I am possibly confused, but if I understand the point of the derivation there, it is to write down the correct equations in I am not sure the motivation for rewriting everything in terms of derivatives at constant This PR proposes to fix the meaning of derivatives such as |
|
@simone-silvestri do you approve? |
|
I think windowed fields like the free surface would still error when being derived in x because it does not have the extra term in z?
This might be ok because we do not use the derivative operator for the advection, but if we want to use that approach, we should do the same for the time derivative, which is not really expressed in terms of operators. In fact we do not timestep at constant z but at constant r (the z changes between time steps in the same cell). So we need to reformulate the equations in r to make sure the time derivative is correct. Timestepping at constant z in a zstar coordinate would be a lagrangian approach (probably I am not 100% sure). |
|
Now for diagnostics this approach is correct, but we need to make sure that dynamics are solved in r-coordinate, not in z-coordinate. |
This is true, but arguably time information should be encapsulated in the coordinate, not in the discretization. Time stepping is the domain of models. At least this PR will fix static generalized vertical discretizations. |
This PR does not change the fact that dynamics must be implemented correctly (this was also true before this PR) |
I think you're right -- if we define dx as "derivative in x at constant z" then this is not a valid operator to apply to the free surface. We need dx_r (derivative in x at constant r). |
|
Ok I guess this is a good compromise, for static generalized coordinates we get the discretization for free, for moving ones we need to make sure that the time derivative is correctly discretized |
|
What do you view this as a compromise between? |
|
I guess the amount of work required to have a new coordinate working with the internals of a model and the correctness of the diagnostics associated with the output of the model. |
How does this increase the amount of work required to get a coordinate working? It decreased the amount of work required for ZStar. What coordinates does this create a problem for? |
|
The primary motivation for this PR is to make it trivial to implement terrain-following static coordinates. This PR eliminates the need for special implementations of horizontal derivatives. I do not understand why a generalizing abstraction wasn't useful for ZStarVerticalCoordinate. At this point, it may be true that we need to revert features implemented for ZStar in order to make this PR work. But that is not a deficiency of the abstraction. That is a problem with the original implementation of ZStar -- rather than finding a general abstraction that would work for both ZStar and other future coordinate implementations, a different, non-general route was taken that, if not reverted, would lead to code duplication. That is of course the reason to solve abstraction problems sooner rather than later. The central point of an abstraction is that it can be used to provide consistent mathematical representations of operations. In other codes, perhaps internal implementation of dynamics are sufficient. In our code, we need abstractions that can be used by both dynamics and users. Note that it is completely unacceptable that diagnostics become meaningless when switching coordinates. Diagnostics are actually more important than dynamics implementation. A dynamics implementation is pointless if the code cannot be used for science. |
|
I realize maybe "compromise" is not the correct term, the thing is that z-based horizontal derivatives do not solve the issue of implementing generic coordinates, that's just what I wanted to express. I think it might happen that you need to explicitly avoid using these operators in many terms (which implies building new operators at constant r) to have correct dynamics. Most of the zstar formulation does not use these derivatives (w is not the vertical velocity, the time derivative is at constant r, and so on...), it is only a matter of the pressure gradient (and closures!). Maybe for terrain following coordinates this is all that is needed and that is great! I agree with pushing forward this PR and I never claimed that diagnostics are not important, so I see this PR more as a positive addition for diagnostics rather than a "generalized abstraction" for implementing vertical coordinates. We need to solve the problem of windowed fields like the free surface though: this PR at the moment is removing support for horizontal derivatives of the free surface in generalized coordinates (https://buildkite.com/clima/oceananigans/builds/28653#019bd4b7-503e-4e26-9f3f-1f52b336c3e5) Indeed, we should probably have two sets of derivatives, one in constant r (just difference divided by spacing) and one in constant z. |
I can give it a go? |
I am happy to tackle this, but also happy to accept help if you want.
We should of course add dx_r and dy_r. These will be one-liners.
Are you sure that is the optimal way to implement it? But indeed, these operators are also needed to compute horizontal buoyancy gradients and isopycnal slopes.
The critical question is not whether this is a complete solution but rather whether it represents a step towards a system of abstractions that is a complete solution. We cannot solve issues with moving coordinates purely with spatial derivative operators. However, if we do open the support of static, terrain following coordinates with these operators, I would argue that this is the correct abstraction strategy. |
|
Ok, I guess to push this PR, we can just substitute the derivative in the |
|
|
||
| @inline explicit_barotropic_pressure_y_gradient(i, j, k, grid, free_surface::ExplicitFreeSurface) = | ||
| free_surface.gravitational_acceleration * ∂yᶜᶠᶜ(i, j, grid.Nz+1, grid, free_surface.displacement) | ||
| free_surface.gravitational_acceleration * δyᶜᶠᶜ(i, j, grid.Nz+1, grid, free_surface.displacement) * Δyᶜᶠᶜ⁻¹(i, j, k, grid) |
There was a problem hiding this comment.
@simone-silvestri do you mind if I add operators for constant_r derivatives?
|
Also @simone-silvestri did you see this comment?
|
1 similar comment
|
Also @simone-silvestri did you see this comment?
|
Resolve conflicts: - Project.toml: take main version (0.105.0), remove old extras/targets sections - hydrostatic_free_surface_tendency_kernel_functions.jl: keep removal of grid_slope_contribution terms (this PR's intent) while adopting the diffusivities→closure_fields rename from main Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add explicit methods for Number arguments on AbstractMutableGrid and MutableImmersedGrid derivative operators to resolve method ambiguities with the base derivative_operators.jl Number methods. Co-Authored-By: Claude Opus 4.6 <[email protected]>
| @inline function ∂xᶠᶜᶜ(i, j, k, grid::AMG, ϕ) | ||
| ∂x_at_r = δxᶠᶜᶜ(i, j, k, grid, ϕ) * Δx⁻¹ᶠᶜᶜ(i, j, k, grid) | ||
| ∂z_ϕ = ∂zᶠᶜᶜ(i, j, k, grid, ϕ) | ||
| ∂x_z = ∂x_zᶠᶜᶜ(i, j, k, grid) | ||
| return ∂x_at_r - ∂x_z * ∂z_ϕ | ||
| end |
There was a problem hiding this comment.
Is that correct in terms of staggering?
When I look at this function signature I think that ϕ must be at a CCC location for its ∂xᶠᶜᶜ(ϕ) to be located at FCC. But inside the body, ϕ seems to be located at a FCF location for its ∂zᶠᶜᶜ(ϕ) to be at FCC:
@inline function ∂xᶠᶜᶜ(i, j, k, grid::AMG, ϕ) # <- ϕ at CCC location
∂x_at_r = δxᶠᶜᶜ(i, j, k, grid, ϕ) * Δx⁻¹ᶠᶜᶜ(i, j, k, grid)
∂z_ϕ = ∂zᶠᶜᶜ(i, j, k, grid, ϕ) # <- ϕ at FCF location?
∂x_z = ∂x_zᶠᶜᶜ(i, j, k, grid)
return ∂x_at_r - ∂x_z * ∂z_ϕ
endAFAIU ∂zᶠᶜᶜ(ϕ) "siliently shifts" ϕ west and below by half an index (CCC->FCF). I understand this could be a good-enough approximation but if the function needs to be correct, shouldn't there be some CCC->FCF interpolation in there?
But maybe I am missing something in how these derivative and difference operators work? Please let me know!
cc @glwagner @simone-silvestri
(FWIW I noticed that because the transport matrix I built became structurally non-symmetric, which should not happen in my model setup.)
There was a problem hiding this comment.
yeah this looks wrong.
I think we have to compute the z derivative and then do a 2D interpolation in x and z to obtain the z-derivative at fcc?
There was a problem hiding this comment.
Will this become a bit too computationally expensive? (horizontal interpolations of vertical derivatives are terribly slow)
There was a problem hiding this comment.
is there another solution?
There was a problem hiding this comment.
I thought this might have been intentional for performance actually, but I didn't know it would be dramatic. Would it make any difference to do the horizontal interpolation first and then take the vertical derivatives?
|
I am testing a one degree resolution ocean model and it seems like with the new derivatives GM / Redi goes crazy, I will try again with #5339 to see if it is an issue of z-derivatives not at the correct position (hopefully). Otherwise I will try to distill a MWE and open an issue. |
It is because there is a huge bug in the pressure gradient |
|
the bug in the pressure gradient does not change much the solution. It's really GM which is completely unphysical: I think this will be much more efficient and avoid us all those interpolations which GM is full of already |

This PR updates the implementation of the generalized vertical discretization (what we now call
MutableVerticalDiscretization) so that horizontal derivatives are interpreted as horizontal derivatives at constantz. I believe this is necessary for code to produce similar / same outcomes for any vertical coordinate. In other words, if we have a static vertical discretization, we assume that horizontal derivatives apply at constantz. So when we change vertical coordinates, we need to specify that derivatives still should apply at constantz.The fact that this simplifies the code is demonstrated in how it allows us to remove a term from the tendency. Previously we had a term
grid_slope_contribution_x... which part of the horizontal pressure gradient. Now that term is incorporated into∂xᶠᶜᶜ.As an aside, I think it is more efficient to evaluate dpdz directly, rather than recomputing buoyancy (which can be expensive, eg involving a 55 term formula).
I'm still not happy with how generalized coordinates are implemented, but I think additional changes should await a future PR and this is a good start.