CliMA / Oceananigans.jl

🌊 Julia software for fast, friendly, flexible, ocean-flavored fluid dynamics on CPUs and GPUs
https://clima.github.io/OceananigansDocumentation/stable
MIT License
965 stars 190 forks source link

Many of the shallow water advection operators appear to be wrong #1866

Closed glwagner closed 1 year ago

glwagner commented 3 years ago

Shallow water advection operators don't look right:

https://github.com/CliMA/Oceananigans.jl/blob/5fbd8cd20c5db8e9b11b6175984e7592a08fc874/src/Models/ShallowWaterModels/shallow_water_advection_operators.jl#L30-L36

In particular the advective fluxes are not multiplied by cell area, even though the flux differences are divided by cell volume. Surely this can't be right? Perhaps I am missing something.

The mass flux divergence is correct, however:

https://github.com/CliMA/Oceananigans.jl/blob/5fbd8cd20c5db8e9b11b6175984e7592a08fc874/src/Models/ShallowWaterModels/shallow_water_advection_operators.jl#L55-L58

But the tracer flux is again incorrect, missing a multiplication by area:

https://github.com/CliMA/Oceananigans.jl/blob/5fbd8cd20c5db8e9b11b6175984e7592a08fc874/src/Models/ShallowWaterModels/shallow_water_advection_operators.jl#L80-L83

The functions that calculate velocity are not correct:

https://github.com/CliMA/Oceananigans.jl/blob/5fbd8cd20c5db8e9b11b6175984e7592a08fc874/src/Models/ShallowWaterModels/shallow_water_advection_operators.jl#L88-L89

because they don't take into account the fact that uh is at cell faces in x, while h is at cell centers.

Finally, I think the momentum flux operators aren't quite right because they don't produce the correct high-order advection stencil:

https://github.com/CliMA/Oceananigans.jl/blob/5fbd8cd20c5db8e9b11b6175984e7592a08fc874/src/Models/ShallowWaterModels/shallow_water_advection_operators.jl#L14-L24

I think what we really want is to express the notion that the velocity u advects the total momentum uh. For this we have to pass uh. / h in the place of the advecting velocity (the first entry) in functions like _advective_momentum_flux_Uu, rather than dividing by h after using second-order interpolation after the advective flux is calculated.

glwagner commented 3 years ago

@francispoulin does it also make sense to write these divergences as two-dimensional (in xy) since that's what we are restricted to for ShallowWaterModel? It might make the code clearer.

francispoulin commented 3 years ago

Very sorry for the problems that you found but I'm glad you found them. I believe when @ali-ramadhan and I put this together we were following other examples but I definitely should have been more careful.

Just so that I understand, instead of having momentum_flux_huu, advection and transport_tracer_flux_x we should have had something involving the area? I'm happy to help fix this where I can.

As for computing the velocity, I hope we can fix that soon as well. I know that ShallowWaterModel is a bit odd as we integrate the mass transports, not the velocities, but we do use the velocity a lot. I wonder if it's worth while computing the velocities (correctly) and then storing those. That should certainly help when we add in closure schemes, since those should be based on the velocities, for the most part.

One option would be to add model.velocities,u and something similar for v, and then access them when we need them. That has the unfortuante effect of storing 5 instead of 3 fields, so it would make things more memory intensive. I don't know if it's better to just compute the velocities everytime we need them?

glwagner commented 3 years ago

No need to apologize, just trying to help.

I think you can form an AbstractOperation for velocities when the model is constructed, eg:

velocities = (u = uh/h, v = vh/h)

These can be stored in ShallowWaterModel.velocities, and used in kernels. They have a getindex method so they'll work with WENO functions too. This doesn't use any extra memory. AbstractOperations perform the calculation uh/h with correct interpolation on the fly.

Just so that I understand, instead of having momentum_flux_huu, advection and transport_tracer_flux_x we should have had something involving the area? I'm happy to help fix this where I can.

We'd write a horizontal divergence either as

div(Q) = 1 / V * (δx(Ax * Qx) + δy(Ay * Qy))

or

div(Q) = 1 / Az * (δx(Δy * Qx) + δy(Δx * Qy))

I think this is written in the docstrings but doesn't appear to be reflected in the code. Correct me if I'm wrong.

glwagner commented 3 years ago

I don't quite understand how the examples can be right without the areas though, so I feel I might be missing something.

francispoulin commented 3 years ago

Maybe part of my confusion is on whether the solution fields, uh,vh,h, are cell averaged quantities or not. If they are then do we need to multipy by the area?

Maybe having docs on the finite volume method, as discussed previously, would help to clear some of this up?

glwagner commented 3 years ago

All quantities are cell averaged. Certainly it would be good to state this in the docs if it is not stated already.

navidcy commented 3 years ago

Well, it's mentioned in the docs.

navidcy commented 3 years ago

1900 brings the finite-volume discussion further up in the Docs/Numerical Implementations.

francispoulin commented 3 years ago

1900 brings the finite-volume discussion further up in the Docs/Numerical Implementations.

I think that's a great idea.

Also, it occurs to me that it would be nice to have another validation code for ShallowWaterModel. The Bickley jet example was good and we confirmed the growth rates, but perhaps a propagatoing equatorial Rossby wave would be fun. This is an exact solution to the equations and we can ensure that the phase speed matches that with theory. Maybe this would help us to ensure that all the integrals are done correctly. I don't think this would be interesting enough to become an example but it might interest some people.

glwagner commented 3 years ago

I think more validation is great.

Integrated cases are split into three categories:

  1. Tests (eg the stuff in test_dynamics.jl for NonhydrostaticModel). These run during CI.
  2. validation/. These are scientific validation cases that often require scientific interpretation or are expensive. These are similar to "Tests" but may lack a quantitative metric of success.
  3. examples/. These are intended to showcase the API and library usage to users. They should not be used as tests, because they are very expensive to run (via Documenter) and to maintain (for one because they have a high standard for code quality).

I suggest adding bona fide Tests and validation, rather than examples, if we are interested in determining the correctness of the code.

francispoulin commented 2 years ago

@glwagner :

I am trying to follow the reasoning as to why the momentum flux does not need the area terms and I have an idea.

First, I have tried to follow the dependencies of the flux function and find the following:

div_hUu -> momentum_flux_huu, -> _advective_momentum_flux_Uu -> advective_momentum_flux_Uu

The final function is defined for either centered of upwinding schemes.

centered_advective_fluxes.jl has a defintion that shows it's proportional to Ax, and hence the area: https://github.com/CliMA/Oceananigans.jl/blob/f1cd43fbfbb5520122f75b2d3fea84f43b4a22e5/src/Advection/centered_advective_fluxes.jl#L15

upwind_biased_advective_fluxes.jl has a definition that shows it is proportional to Ax as well: https://github.com/CliMA/Oceananigans.jl/blob/f1cd43fbfbb5520122f75b2d3fea84f43b4a22e5/src/Advection/upwind_biased_advective_fluxes.jl#L24

Something similar is true for advective_tracer_flux, and those can be found in the same files.

Does this answer the question why there should not be any area terms in the flux?

If this convention is confusing, do we want to do something different?

francispoulin commented 2 years ago

Also, it occurs to me that dividing the difference terms by the volumes in ShallowWaterModel seems silly. What do people think of replacing those with areas instead?

francispoulin commented 2 years ago

@glwagner : I don't know that this approaches achieves the high order that we can achieve and I am happy to try something else.

Also, it would be nice to have a test that does this. The test that we have for advection assumes that h is constant initially, and that migth be too simple to see whether we always achieve the high order that we want to achieve.

glwagner commented 1 year ago

I'm closing this issue because I'm judging that it's not of current, timely relevance to Oceananigans development. If you would like to make it a higher priority or if you think the issue was closed in error please feel free to re-open.