-
Notifications
You must be signed in to change notification settings - Fork 233
Ax, Ay and Az are negative in a Tripolar grid #4318
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
Comments
cc @navidcy |
out of curiosity, have you tried other grids? |
Yes I tried |
I trimmed down the MWE a bit so we don't need ClimaOcean. using Oceananigans
using Oceananigans.Operators: Ax, Ay, Az
Nx, Ny, Nz = 40, 30, 10
grid = TripolarGrid(size = (Nx, Ny, Nz),
z = (-5000, 0),
first_pole_longitude = 70,
north_poles_latitude = 55)
f = XFaceField(grid)
set!(f, 1)
f_dAx = Field(f * Ax)
compute!(f_dAx)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAx, :, :, 1), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig |
Also f_dAy = Field(f * Ay)
compute!(f_dAy)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAy, :, :, 3), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig and f_dAz = Field(f * Az)
compute!(f_dAz)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAz, :, :, 3), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig |
Btw, if f = CenterField(grid) everything seems reasonable. |
Hmmm, that is because of the northern boundary condition which, for x-face fields, is assumed to need a sign switch across the fold (velocities need a sign switch across the fold). To fix this problem we need to have a definition of |
@simone-silvestri is it because we didn't fill the halos? E.g., if I fill the halos of using Oceananigans
using Oceananigans.Operators: Ax, Ay, Az
Nx, Ny, Nz = 40, 30, 10
grid = TripolarGrid(size = (Nx, Ny, Nz),
z = (-5000, 0),
first_pole_longitude = 70,
north_poles_latitude = 55)
f = XFaceField(grid)
set!(f, 1)
using Oceananigans.BoundaryConditions: fill_halo_regions!
fill_halo_regions!(f)
f_dAx = Field(f * Ax)
compute!(f_dAx)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAx, :, :, 3), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Ax.png", fig)
f_dAy = Field(f * Ay)
compute!(f_dAy)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAy, :, :, 3), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Ay.png", fig)
f_dAz = Field(f * Az)
compute!(f_dAz)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAz, :, :, 3), colorrange = extrema(f_dA), colormap = :balance)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Az.png", fig) |
Hah, ok this is probably unexpected. I thought that the BCs are the reason for the negative values. |
@navidcy I cannot reproduce your results, the negative line is always there (provided I fix the heatmap extrema because in your snipper you are using a non defined global variable) |
Oh darn! using Oceananigans
using Oceananigans.Operators: Ax, Ay, Az
using GLMakie
Nx, Ny, Nz = 40, 30, 10
grid = TripolarGrid(size = (Nx, Ny, Nz),
z = (-5000, 0),
first_pole_longitude = 70,
north_poles_latitude = 55)
f = CenterField(grid)
set!(f, 1)
using Oceananigans.BoundaryConditions: fill_halo_regions!
fill_halo_regions!(f)
f_dAx = Field(f * Ax)
compute!(f_dAx)
max_abs = maximum(abs, f_dAx)
extrema_f_dA = extrema(f_dAx)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAx, :, :, 1), colorrange = (-max_abs, max_abs), colormap = :balance)
Label(fig[0, :], "minimum = $(extrema_f_dA[1]), maximum = $(extrema_f_dA[2])", tellwidth=false)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Ax.png", fig) f_dAy = Field(f * Ay)
compute!(f_dAy)
max_abs = maximum(abs, f_dAy)
extrema_f_dA = extrema(f_dAy)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAy, :, :, 1), colorrange = (-max_abs, max_abs), colormap = :balance)
Label(fig[0, :], "minimum = $(extrema_f_dA[1]), maximum = $(extrema_f_dA[2])", tellwidth=false)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Ay.png", fig) f_dAz = Field(f * Az)
compute!(f_dAz)
max_abs = maximum(abs, f_dAz)
extrema_f_dA = extrema(f_dAz)
fig = Figure()
ax = Axis(fig[1, 1])
hm = heatmap!(ax, interior(f_dAz, :, :, 1), colorrange = (-max_abs, max_abs), colormap = :balance)
Label(fig[0, :], "minimum = $(extrema_f_dA[1]), maximum = $(extrema_f_dA[2])", tellwidth=false)
Colorbar(fig[1, 2], hm)
fig
save("tripolar_f_Az.png", fig) |
yeah the difference is that I think though, the best thing to do is to write an abstraction for vector field |
It's better to not assume that This is also how boundary conditions work. |
And just to clarify, we already have a kind of vector abstraction in that we implement for other topologies than
but
the same logic should be applied to the implementation of boundary conditions for |
Yeah, that is a bit lacking as an abstraction. We leave out fields that are auxiliary but vector components (tendencies for example). Also it does not distinguish right and left boundary condition. I think This example and the needs of a right folded boundary shows the pitfalls of this design and calls for a redesign of this abstraction. |
I was already suspecting that this piece of code was not well designed for our goals when introducing the distributed communication that does not fit within this abstraction (i.e. we need to inject boundary conditions manually). |
I think we just have to define the default so that it is not assuming a vector, and then to specify vector where needed in the model constructor. For other cases we use the word "auxiliary" for the default and "prognostic" for the vector case (because the only prognostic fields at |
Why does |
That's a good point! I'm also confused. |
by construction the half line on the right hand side of the grid, for fields that are centered in y, is redundant. So it cannot really be considered as "interior" probably. At the beginning the halos were not changing this line, that would drift in time compared to the left hand side because of finite precision errors propagating. We have decided subsequently that it is best to have only one source of truth and, therefore, to substitute those values with the ones on the left hand side here CliMA/OrthogonalSphericalShellGrids.jl#58. I think this is still the best strategy numerically. The inconsistency is that it is quite difficult to enforce on distributed tripolar grids. |
why does the fold overlap? can we fold the grid so that the two boundaries touch rather than becoming enmeshed? |
I am trying to compute the velocity multiplied by the grid cell area (Ax, Ay or Az in Oceananigans). However, I seem to have stumbled upon a confusing feature of these Operators in that they are negative in some places in a Tripolar grid.
As a simple example:
gives
where the minimum is a negative value? I get the same issue with
Ay
andAz
. Any guidance on why this is would be much appreciated.Also, I checked and it doesn't seem to be to do with halos:
The text was updated successfully, but these errors were encountered: