-
Notifications
You must be signed in to change notification settings - Fork 193
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
Convert Grid and Field structs to isbitstype #59
Comments
Just noticed the title! Duh. Anyways: abstract type Grid end
struct RegularCartesianGrid{T<:AbstractFloat,TxC} <: Grid
dim::Int
# Number of grid points in (x,y,z).
Nx::Int
Ny::Int
Nz::Int
# Domain size [m].
Lx::T
Ly::T
Lz::T
# Grid spacing [m].
Δx::T
Δy::T
Δz::T
# Cell face areas [m²].
Ax::T
Ay::T
Az::T
# Volume of a cell [m³].
V::T
# Ranges of coordinates at the centers of the cells.
xC::TxC
yC::TxC
zC::TxC
# Ranges of coordinates at the faces of the cells.
xF::TxC
yF::TxC
zF::TxC
end
function RegularCartesianGrid(T, N, L)
@assert length(N) == 3 && length(L) == 3 "N, L must have all three dimensions to specify which dimensions are used."
@assert all(L .> 0) "Domain lengths must be nonzero and positive!"
# Count the number of dimensions with 1 grid point, i.e. the number of flat
# dimensions, and use it to determine the dimension of the model.
num_flat_dims = count(i->(i==1), N)
dim = 3 - num_flat_dims
@assert 1 <= dim <= 3 "Only 1D, 2D, and 3D grids are supported right now."
Nx, Ny, Nz = N
Lx, Ly, Lz = L
dim == 2 && @assert Nx == 1 || Ny == 1 || Nz == 1 "For 2D grids, Nx, Ny, or Nz must be 1."
dim == 3 && @assert Nx != 1 && Ny != 1 && Nz != 1 "For 3D grid, cannot have dimensions of size 1."
Δx = Lx / Nx
Δy = Ly / Ny
Δz = Lz / Nz
Ax = Δy*Δz
Ay = Δx*Δz
Az = Δx*Δy
V = Δx*Δy*Δz
xC = Δx/2:Δx:Lx
yC = Δy/2:Δy:Ly
zC = -Δz/2:-Δz:-Lz
xF = 0:Δx:Lx
yF = 0:Δy:Ly
zF = 0:-Δz:-Lz
RegularCartesianGrid{T,typeof(xC)}(dim, Nx, Ny, Nz, Lx, Ly, Lz, Δx, Δy, Δz, Ax, Ay,
Az, V, xC, yC, zC, xF, yF, zF)
end
RegularCartesianGrid(metadata::ModelMetadata, N, L) = RegularCartesianGrid(metadata.float_type, N, L) then <somehow include above code>
julia> g = RegularCartesianGrid(Float64, (3, 3, 3), (1.0, 1.0, 1.0))
...
julia> isbitstype(typeof(g))
true |
Was about to note the same thing: https://github.com/ali-ramadhan/Oceananigans.jl/blob/f7ba1ce353eaa6abc2b3c9381fa22fe53ba27fce/src/grids.jl#L33-L46 need to be typed to be isbits. |
Perhaps move this to v0.6? |
Agreed. Useful and related comment
|
@jm-c and I talked today and we have an additional point to make (this is related to #115 as well). Notice first that the operators @inline function δz_f2c(f, Nz, i, j, k)
if k == Nz
@inbounds return f[i, j, k]
else
@inbounds return f[i, j, k] - f[i, j, k+1]
end
end
@inline function δz_e2f(f, Nz, i, j, k)
if k == Nz
@inbounds return f[i, j, k]
else
@inbounds return f[i, j, k] - f[i, j, k+1]
end
end Our solution: abstract type Location end
struct Center end
struct Interface end
struct Field{Lx<:Location, Ly<:Location, Lz<:Location, A, G}
data::A
grid::G
end we then need only two δz(f::Field{Lx, Ly, Lz}, i, j, k) where {Lx, Ly, Lz<:Center} = ...
δz(f::Field{Lx, Ly, Lz}, i, j, k) where {Lx, Ly, Lz<:Interface} = ... |
Dispatching on the location as a parameterized type looks neat, would definitely clean things up! Thanks for coding up the example. I see how this would clean things up for @inline function δz_f2c(f, Nz, i, j, k)
if k == Nz
@inbounds return f[i, j, k]
else
@inbounds return f[i, j, k] - f[i, j, k+1]
end
end
@inline function δz_f2e(f, Nz, i, j, k)
if k == 1
return 0
else
@inbounds return f[i, j, k-1] - f[i, j, k]
end
end To me it looks like they both fit δz(f::Field{Lx, Ly, Lz}, i, j, k) where {Lx, Ly, Lz<:Interface} = ... so I'm not sure how dispatch between the two. |
“face to edge” delta z must refer to an operation on an x-interface or
y-interface — not a z-interface to an edge?
…On Sat, Mar 9, 2019 at 8:38 AM Ali Ramadhan ***@***.***> wrote:
Dispatching on the location as a parameterized type looks neat, would
definitely clean things up! Thanks for coding up the example.
I see how this would clean things up for δz_f2c and δz_e2f but the δz
operator also needs to know onto which location to interpolate, so how
would this work with δz_f2c and δz_f2e?
@inline function δz_f2c(f, Nz, i, j, k)
if k == Nz
@inbounds return f[i, j, k]
else
@inbounds return f[i, j, k] - f[i, j, k+1]
end
end
@inline function δz_f2e(f, Nz, i, j, k)
if k == 1
return 0
else
@inbounds return f[i, j, k-1] - f[i, j, k]
end
end
To me it looks like they both fit
δz(f::Field{Lx, Ly, Lz}, i, j, k) where {Lx, Ly, Lz<:Interface} = ...
so I'm not sure how dispatch between the two.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#59 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AOkIBkzcm1N5EI8VXyk1UgseDS6muPk9ks5vU7lYgaJpZM4bEKew>
.
|
Ah yes I remember @jm-c's concern now! Yes, just "face" and "edge" are ambiguous. So your proposed solution will make it explicit exactly which interface the field is being interpolated from and to, which will be nice. |
An “edge” is the case in which 2 of Lx, Ly, or Lz are “interface”. We just
don’t need special notation. This method of specifying locations in a cube
is simpler, but also more general.
…On Sat, Mar 9, 2019 at 8:52 AM Ali Ramadhan ***@***.***> wrote:
Ah yes I remember @jm-c <https://github.com/jm-c>'s concern now! Yes,
just "face" and "edge" are ambiguous.
So your proposed solution will make it explicit exactly which interface
the field is being interpolated from and to, which will be nice.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#59 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AOkIBlzM_EBoVLsfUYqw-V_v_Pe2admmks5vU7yqgaJpZM4bEKew>
.
|
I'm finally starting to work on this issue now. I should be able to refactor all the code without changing any of the numerics. Resolving this issue will also resolve #60. I have moved the slightly separate issue of just using cell centers and cell interfaces (and explicitly stating which interface) to #146 as that will change the operators and numerics, and may be trickier to get right. I've added some goals to the original post. |
Hit a slight roadblock as the struct CellField{A<:AbstractArray,G<:Grid} <: Field
data::A
grid::G
end since However, @vchuravy points out that a So we'll have to figure out how to adapt our I should also check out the |
Oh no! We can still use the |
Well, road block might not be the right word as I'm sure we can figure it out. So we can already use the |
@peterahrens suggested removing
ModelMetadata
fromField
structs and make theGrid
a parameter, i.e.Grid{T,G}
then it should be isbitstype. It's not isbits right now because T<:AbstractArray.Then we should be able to use some abstractions in the CPU/GPU element-wise kernels as well as multiple dispatch and won't need to have
δx_c2f
,δx_f2c
,δx_e2f
,δx_f2e
, etc.Some goals for guidance:
isbitstype
.isbitstype
. Just construct a bunch of grids, fields, and forcing functions and test that they are indeedisbitstype
.isbitstype
abstractions to make sure performance hasn't degraded.The text was updated successfully, but these errors were encountered: