Adaptive implicit vertical advection#5604
Conversation
…vertical-advection
…vertical-advection
|
Let's avoid a wrapper if at all possible (instead you can add a property to the model). Using a wrapper makes the user interface hard; we can't make it a default option easily. Generally wrappers should be a method of last resort, only if they are ABSOLUTELY the worst of many other evil options, in my opinion. |
|
I would avoid a property in the model, it's an advection scheme property. Another option is to add an |
…CliMA/Oceananigans.jl into ss/adaptive-implicit-vertical-advection
It's really a model property, because it has to be supported by changing the whole algorithm (ie this cannot be implemented for models that do not have tridiagonal solvers already) |
|
As a model property leads to the usual design problem of having HydrostaticFreeSurfaceModel(; advection = nothing, implicit_advection = true)which creates conflicting keyword arguments. I like the wrapper approach which I feel is also quite easy and maintainable but this is a personal preference. The implicit solver is a timestepper property, not a model property, so if we want to be completely clean in the design then the time discretization kwarg should belong to the timestepper. However this requires a redesign of the closures which follow the design I am proposing here for the advection. |
|
So I would be ok in mimicking the closure's approach where the "time discretization" belongs to the advection scheme. |
The point is that this is FAR lesser evil than the wrapper . |
|
Wrappers have created a lot of issues in the past (compared to a simple validation check) and also impact compile time |
|
Otherwise, I am also ok taking the more principled route of redesigning the timestepper to include the vertical time discretization but will require a couple of more PRs |
I'm ok with embedding in the advection scheme. Note, validation is required for ANY approach, so the problem of "invalid combinations" is not an actual differentiator. |
I don't think you need to change the time-stepper here, or at least our discussion does not bear on whether or not to change the timestepper. |
…CliMA/Oceananigans.jl into ss/adaptive-implicit-vertical-advection
Benchmark ComparisonBenchmark Comparison: PR vs Main
NSYS Kernel ProfilingEarthOcean_tripolar_360x180x50_F64_WENOVectorInvariantDefault_WENO7_CATKE_2tr
|
|
@glwagner this PR should be ready to review. (I have also checked there is no performance regression for including the time discretization in the advection schemes). |
Benchmark ComparisonBenchmark Comparison: PR vs Main
NSYS Kernel ProfilingEarthOcean_tripolar_360x180x50_F64_WENOVectorInvariantDefault_WENO7_CATKE_2tr
|
|
|
||
| A fully-explicit time-discretization of a `TurbulenceClosure`. | ||
| """ | ||
| struct ExplicitTimeDiscretization <: AbstractTimeDiscretization end |
There was a problem hiding this comment.
There is also an ETD in TurbulenceClosures? Should this go somewhere more general?
There was a problem hiding this comment.
This is the same one that is in TurbulenceClosures, I moved it up to Advection.
There was a problem hiding this comment.
It's weird that "VerticallyImplicitTimeDiscretization" (used for closures) is defined in Advection
There was a problem hiding this comment.
I suggest putting this into TimeSteppers module, which is loaded before Advection:
Oceananigans.jl/src/Oceananigans.jl
Lines 233 to 234 in c2c4d1f
There was a problem hiding this comment.
sounds good to me!
| @inline bias(u::Number) = ifelse(u > 0, LeftBias, RightBias) | ||
|
|
||
| @inline function advective_momentum_flux_Uu(i, j, k, grid, scheme::UpwindScheme, U, u) | ||
| @inline function advective_momentum_flux_Uu(i, j, k, grid, scheme::UpwindScheme, ::ETD, U, u) |
There was a problem hiding this comment.
I'm slightly confused by this. The time discretization is also inside scheme, right?
There was a problem hiding this comment.
yeah but this is to dispatch, so we unwrap the time_discretization(scheme) and these fluxes are the "Explicit" ones.
There was a problem hiding this comment.
another strategy is to define ExplicitUpwindScheme right? This seems a bit simpler. Curious what you think.
There was a problem hiding this comment.
we could also do like the closures do and just reroute advective_momentum_flux_Uu(i, j, k, grid, scheme, ::ETD, U, u) to advective_momentum_flux_Uu(i, j, k, grid, scheme, U, u) and keep the same code in this file. This would allow us to avoid aliases
There was a problem hiding this comment.
Oh I see, is that the benefit of using the extra argument? I don't completely grasp the totality of this design
There was a problem hiding this comment.
the idea here is that the _advective_flux (once the order is decided) reroute to
advective_flux(..., td, ...) so that we select what happens, then if it is adaptive vertically implicit we have this extra step of computing the "explicit" vertical velocity otherwise business as usual. It is true that ETD is business as usual so we can remove the extra argument in case of an ETD which leaves the previous functions untouched. This would basically be the same design as
In the current state the difference is that we are not removing the extra argument.
There was a problem hiding this comment.
So in the current state, if we want to define a new advecitve flux, we define it for the "ETD" case with explicit dispatch -- is that right?
There was a problem hiding this comment.
yes that would be the route. Otherwise if we add the rerouting that removes the extra argument when we do not need to explicitly specify ETD
…CliMA/Oceananigans.jl into ss/adaptive-implicit-vertical-advection
Benchmark ComparisonBenchmark Comparison: PR vs Main
NSYS Kernel ProfilingEarthOcean_tripolar_360x180x50_F64_WENOVectorInvariantDefault_WENO7_CATKE_2tr
|
Benchmark ComparisonBenchmark Comparison: PR vs Main
NSYS Kernel ProfilingEarthOcean_tripolar_360x180x50_F64_WENOVectorInvariantDefault_WENO7_CATKE_2tr
|
this PR implements a new advection configuration, an AdaptiveImplicitVerticalAdvection
that wraps around an advection scheme (scheme = AdaptiveImplicitVerticalAdvection(explicit_scheme = WENO(), cfl = 0.7)for example)constructed by adding a
time_discretizationkwarg to the advection schemes (by defaultExplicitTimeDiscretization()) enabled (for example) by passingAdaptiveImplicitTimeDiscretization(; maximum_explicit_cfl)to treat implicitly part of vertical advection.
In particular it split the advection in an explicit part that advects with the
schemeusing a vertical velocitywe = w * max(cfl / scheme.cfl)and an implicit part that advects with an upwind first order scheme using a velocity ofwi = w - we.We reuse the implicit tridiagonal solver to advect implicitly. A caveat (for the moment), is that the vertical velocity itself does not participate in this split. An example of a comparison between a reference, a fully explicit scheme and AIVA can be found in the validation/implicit_vertical_advection folder. It advects a gaussian, these are the results:
and the figure it produces:
