-
Notifications
You must be signed in to change notification settings - Fork 259
(0.99.2) Add XESMF.jl extension to use xESMF to compute tracer regridding weights #4782
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
Conversation
|
Great! A few comments off the bat:
I am happy to implement these changes if that's ok @taimoorsohail ? |
|
Ah and another thing --- |
|
Yep @glwagner very happy for you to implement. Note that I did switch to PythonCall at some point and then I reverted back. I can't remember why exactly, it should be totally fine though... |
|
By the way, xESMF requires calling MPI to work, as far as I could tell. That means that if you are using the regridder you need to call |
ext/OceananigansPythonCallExt.jl
Outdated
| end | ||
|
|
||
| function coordinate_dataset(grid::SomeTripolarGrid) | ||
| lat = Array(grid.φᶜᶜᵃ[1:grid.Nx, 1:grid.Ny]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, the preferred syntax is
lon, lat, z = nodes(grid, Center(), Center(), Center())
I started working on transitioning to an extension |
…com/CliMA/Oceananigans.jl into ts/implement-conservative-regridder
We are committing on top of each other, so lets coordinate |
…A/Oceananigans.jl into ts/implement-conservative-regridder
Co-authored-by: Simone Silvestri <[email protected]>
Co-authored-by: Simone Silvestri <[email protected]>
|
@simone-silvestri , using NumericalEarth/XESMF.jl#16 with the MWE below I get: using Oceananigans
using XESMF
tg = TripolarGrid(; size=(360, 170, 1), z = (-1, 0), southernmost_latitude = -80)
llg = LatitudeLongitudeGrid(; size=(360, 180, 1), z = (-1, 0),
longitude=(0, 360), latitude=(-82, 90))
src_field = CenterField(tg)
dst_field = CenterField(llg)
λ₀, φ₀ = 150, 30. # degrees
width = 12 # degrees
set!(src_field, (λ, φ, z) -> exp(-((λ - λ₀)^2 + (φ - φ₀)^2) / 2width^2))
regridder = XESMF.Regridder(dst_field, src_field, method="conservative")
regrid!(dst_field, regridder, src_field)julia> using Oceananigans
julia> using XESMF
julia> tg = TripolarGrid(; size=(360, 170, 1), z = (-1, 0), southernmost_latitude = -80)
360×170×1 OrthogonalSphericalShellGrid{Float64, Periodic, RightConnected, Bounded} on CPU with 4×4×4 halo and with precomputed metrics
├── centered at (λ, φ) = (70.0, 1.8005)
├── longitude: Periodic extent 360.156 degrees variably spaced with min(Δλ)=0.00798438, max(Δλ)=1.05373
├── latitude: Oceananigans.Grids.RightConnected extent 171.0 degrees variably spaced with min(Δφ)=0.0127345, max(Δφ)=1.00592
└── z: Bounded z ∈ [-1.0, 0.0] regularly spaced with Δz=1.0
julia> llg = LatitudeLongitudeGrid(; size=(360, 180, 1), z = (-1, 0),
longitude=(0, 360), latitude=(-82, 90))
360×180×1 LatitudeLongitudeGrid{Float64, Periodic, Bounded, Bounded} on CPU with 3×3×1 halo and with precomputed metrics
├── longitude: Periodic λ ∈ [0.0, 360.0) regularly spaced with Δλ=1.0
├── latitude: Bounded φ ∈ [-82.0, 90.0] regularly spaced with Δφ=0.955556
└── z: Bounded z ∈ [-1.0, 0.0] regularly spaced with Δz=1.0
julia> src_field = CenterField(tg)
360×170×1 Field{Center, Center, Center} on OrthogonalSphericalShellGrid on CPU
├── grid: 360×170×1 OrthogonalSphericalShellGrid{Float64, Periodic, RightConnected, Bounded} on CPU with 4×4×4 halo and with precomputed metrics
├── boundary conditions: FieldBoundaryConditions
│ └── west: Periodic, east: Periodic, south: ZeroFlux, north: Zipper(1.0), bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing
└── data: 368×178×9 OffsetArray(::Array{Float64, 3}, -3:364, -3:174, -3:5) with eltype Float64 with indices -3:364×-3:174×-3:5
└── max=0.0, min=0.0, mean=0.0
julia> dst_field = CenterField(llg)
360×180×1 Field{Center, Center, Center} on LatitudeLongitudeGrid on CPU
├── grid: 360×180×1 LatitudeLongitudeGrid{Float64, Periodic, Bounded, Bounded} on CPU with 3×3×1 halo and with precomputed metrics
├── boundary conditions: FieldBoundaryConditions
│ └── west: Periodic, east: Periodic, south: ZeroFlux, north: Value, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing
└── data: 366×186×3 OffsetArray(::Array{Float64, 3}, -2:363, -2:183, 0:2) with eltype Float64 with indices -2:363×-2:183×0:2
└── max=0.0, min=0.0, mean=0.0
julia> λ₀, φ₀ = 150, 30. # degrees
(150, 30.0)
julia> width = 12 # degrees
12
julia> set!(src_field, (λ, φ, z) -> exp(-((λ - λ₀)^2 + (φ - φ₀)^2) / 2width^2))
360×170×1 Field{Center, Center, Center} on OrthogonalSphericalShellGrid on CPU
├── grid: 360×170×1 OrthogonalSphericalShellGrid{Float64, Periodic, RightConnected, Bounded} on CPU with 4×4×4 halo and with precomputed metrics
├── boundary conditions: FieldBoundaryConditions
│ └── west: Periodic, east: Periodic, south: ZeroFlux, north: Zipper(1.0), bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing
└── data: 368×178×9 OffsetArray(::Array{Float64, 3}, -3:364, -3:174, -3:5) with eltype Float64 with indices -3:364×-3:174×-3:5
└── max=0.998852, min=3.66505e-85, mean=0.0130418
julia> regridder = XESMF.Regridder(dst_field, src_field, method="conservative")
Conservative Regridder
├── weights: 64800×61200 SparseArrays.SparseMatrixCSC{Float64, Int64} with 263516 stored entries
├── src_temp: 61200-element Vector{Float64}
└── dst_temp: 64800-element Vector{Float64}
julia> regrid!(dst_field, regridder, src_field)
ERROR: UndefVarError: `regridder` not defined
Stacktrace:
[1] regrid!(dst_field::Field{…}, regrider::XESMF.Regridder{…}, src_field::Field{…})
@ OceananigansXESMFExt ~/Library/CloudStorage/OneDrive-TheUniversityofMelbourne/Documents/Research/Oceananigans.jl-v4/ext/OceananigansXESMFExt.jl:190
[2] top-level scope
@ REPL[34]:1
Some type information was truncated. Use `show(err)` to see complete types. |
|
oh I have a typo... nevermind |
|
I get this: julia> regridder = XESMF.Regridder(dst_field, src_field, method="conservative")
conservative Regridder
├── weights: 64800×61200 SparseArrays.SparseMatrixCSC{Float64, Int64} with 263516 stored entries
├── src_temp: 61200-element Vector{Float64}
└── dst_temp: 64800-element Vector{Float64}
julia> regrid!(dst_field, regridder, src_field)
ERROR: UndefVarError: `topology` not defined
Stacktrace:
[1] regrid!(dst_field::Field{…}, regrider::XESMF.Regridder{…}, src_field::Field{…})
@ OceananigansXESMFExt ~/development/TestOceananigans.jl/ext/OceananigansXESMFExt.jl:182
[2] top-level scope
@ REPL[13]:1
Some type information was truncated. Use `show(err)` to see complete types.I think we need using Oceananigans.Grids: topology |
|
just with this regridder(vec(interior(dst_field)), vec(interior(src_field)))it works |
|
Looks great! Should we consider the case for regridding in GPU as well? I was trying it out here function regrid!(dst, weights::CuSparseMatrixCSC, src)
vec(dst) .= weights * CuArray(vec(src))
endBy the same approach to do it over the entire 3D function regrid!(dst::AbstractField, src::AbstractField, interpolator::BilinearInterpolator)
weights = interpolator.weights
# Get the interior data
dst_data = interior(dst)
src_data = interior(src)
Nz = size(src_data, 3)
for k in 1:Nz
src_slice = view(src_data, :, :, k)
dst_slice = view(dst_data, :, :, k)
regrid!(dst_slice, weights, src_slice)
end
return dst
endI haven't put too much thought into this, and it looks inefficient as I had to allocate another Perhaps a better way to go about this is to actually write our own sparse matrix multiply? Doing that can allow us to dispatch kernels to do the regridding over all vertical levels at the same time. It doesn't seem too hard to write but I also haven't thought very deeply about it. |
|
I'm merging this as a good starting point and will continue working on it. Some outstanding issues are:
|
I have created a wrapper for xESMF (python package) so we can generally regrid any field from source to destination. At the moment, the PR doesn't include vertical regrinding (i.e., source and destinations vertical grids need to be the same).
Note: