@@ -9,24 +9,28 @@ using Oceananigans.Grids: AbstractGrid, λnodes, φnodes, Center, Face, total_le
99import Oceananigans. Fields: regrid!
1010import XESMF: Regridder
1111
12- # permutedims below is used because Python's xESMF expects
13- # 2D arrays with (x, y) coordinates with y varying in dim=1 and x varying in dim=2
12+ node_array (ξ:: AbstractMatrix , Nx, Ny) = view (ξ, 1 : Nx, 1 : Ny)
1413
15- node_array (ξ:: AbstractMatrix , Nx, Ny) = permutedims (view (ξ, 1 : Nx, 1 : Ny), (2 , 1 ))
16- vertex_array (ξ:: AbstractMatrix , Nx, Ny) = permutedims (view (ξ, 1 : Nx+ 1 , 1 : Ny+ 1 ), (2 , 1 ))
17-
18- x_node_array (x:: AbstractVector , Nx, Ny) = permutedims (repeat (view (x, 1 : Nx), 1 , Ny), (2 , 1 ))
14+ x_node_array (x:: AbstractVector , Nx, Ny) = repeat (view (x, 1 : Nx), 1 , Ny)
1915x_node_array (x:: AbstractMatrix , Nx, Ny) = node_array (x, Nx, Ny)
2016
21- y_node_array (y:: AbstractVector , Nx, Ny) = repeat (view (y, 1 : Ny), 1 , Nx )
17+ y_node_array (y:: AbstractVector , Nx, Ny) = repeat (transpose ( view (y, 1 : Ny)), Nx, 1 )
2218y_node_array (y:: AbstractMatrix , Nx, Ny) = node_array (y, Nx, Ny)
2319
24- x_vertex_array (x:: AbstractVector , Nx, Ny) = permutedims (repeat (view (x, 1 : Nx+ 1 ), 1 , Ny+ 1 ), (2 , 1 ))
20+ vertex_array (ξ:: AbstractMatrix , Nx, Ny) = view (ξ, 1 : Nx+ 1 , 1 : Ny+ 1 )
21+
22+ x_vertex_array (x:: AbstractVector , Nx, Ny) = repeat (view (x, 1 : Nx+ 1 ), 1 , Ny+ 1 )
2523x_vertex_array (x:: AbstractMatrix , Nx, Ny) = vertex_array (x, Nx, Ny)
2624
27- y_vertex_array (y:: AbstractVector , Nx, Ny) = repeat (view (y, 1 : Ny+ 1 ), 1 , Nx + 1 )
25+ y_vertex_array (y:: AbstractVector , Nx, Ny) = repeat (transpose ( view (y, 1 : Ny+ 1 )), Nx + 1 , 1 )
2826y_vertex_array (y:: AbstractMatrix , Nx, Ny) = vertex_array (y, Nx, Ny)
2927
28+ """
29+ xesmf_coordinates(grid::AbstractGrid, ℓx, ℓy, ℓz)
30+
31+ Extract the coordinates (latitude/longitude) and the coordinates' bounds from
32+ `grid` at locations `ℓx, ℓy, ℓz`.
33+ """
3034function xesmf_coordinates (grid:: AbstractGrid , ℓx, ℓy, ℓz)
3135 Nx, Ny, Nz = size (grid)
3236
@@ -44,23 +48,26 @@ function xesmf_coordinates(grid::AbstractGrid, ℓx, ℓy, ℓz)
4448 λv = x_vertex_array (λv, Nx, Ny)
4549 φv = y_vertex_array (φv, Nx, Ny)
4650
47- return Dict (" lat" => φ, # φ is latitude
48- " lon" => λ, # λ is longitude
49- " lat_b" => φv,
50- " lon_b" => λv)
51- end
52-
53- function xesmf_coordinates (dst_field:: AbstractField , src_field:: AbstractField )
54-
55- ℓx, ℓy, ℓz = Oceananigans. Fields. instantiated_location (src_field)
51+ # Python's xESMF expects 2D arrays with (x, y) coordinates
52+ # in which y varies in dim=1 and x varies in dim=2
53+ # therefore we transpose the coordinate matrices
54+ coords_dictionary = Dict (" lat" => permutedims (φ, (2 , 1 )), # φ is latitude
55+ " lon" => permutedims (λ, (2 , 1 )), # λ is longitude
56+ " lat_b" => permutedims (φv, (2 , 1 )),
57+ " lon_b" => permutedims (λv, (2 , 1 )))
5658
57- dst_grid = dst_field . grid
58- src_grid = src_field . grid
59+ return coords_dictionary
60+ end
5961
60- dst_coordinates = xesmf_coordinates (dst_grid, ℓx, ℓy, ℓz)
61- src_coordinates = xesmf_coordinates (src_grid, ℓx, ℓy, ℓz )
62+ """
63+ xesmf_coordinates(field::AbstractField )
6264
63- return dst_coordinates, src_coordinates
65+ Extract the coordinates (latitude/longitude) and the coordinates' bounds from
66+ the `field`'s grid.
67+ """
68+ function xesmf_coordinates (field:: AbstractField )
69+ ℓx, ℓy, ℓz = Oceananigans. Fields. instantiated_location (field)
70+ return xesmf_coordinates (field. grid, ℓx, ℓy, ℓz)
6471end
6572
6673"""
@@ -89,20 +96,24 @@ For more information, see the Python xESMF documentation at:
8996Example
9097=======
9198
92- ```@example
99+ To create a regridder for two fields that live on different grids.
100+
101+ ```@example regridding
93102using Oceananigans
94103using XESMF
95104
96105z = (-1, 0)
97- tg = TripolarGrid(; size=(360, 170 , 1), z, southernmost_latitude = -80)
98- llg = LatitudeLongitudeGrid(; size=(360, 180 , 1), z,
106+ tg = TripolarGrid(; size=(180, 85 , 1), z, southernmost_latitude = -80)
107+ llg = LatitudeLongitudeGrid(; size=(170, 80 , 1), z,
99108 longitude=(0, 360), latitude=(-82, 90))
100109
101110src_field = CenterField(tg)
102111dst_field = CenterField(llg)
103112
104- regridder = Oceananigans.Fields .Regridder(dst_field, src_field, method="conservative")
113+ regridder = XESMF .Regridder(dst_field, src_field, method="conservative")
105114```
115+
116+ We can use the above regridder to regrid via [`regrid!`](@ref).
106117"""
107118function Regridder (dst_field:: AbstractField , src_field:: AbstractField ; method= " conservative" )
108119
@@ -117,7 +128,8 @@ function Regridder(dst_field::AbstractField, src_field::AbstractField; method="c
117128 dst_Nz = size (dst_field)[3 ]
118129 @assert src_field. grid. z. cᵃᵃᶠ[1 : src_Nz+ 1 ] == dst_field. grid. z. cᵃᵃᶠ[1 : dst_Nz+ 1 ]
119130
120- dst_coordinates, src_coordinates = xesmf_coordinates (dst_field, src_field)
131+ dst_coordinates = xesmf_coordinates (dst_field)
132+ src_coordinates = xesmf_coordinates (src_field)
121133 periodic = Oceananigans. Grids. topology (src_field. grid, 1 ) === Periodic ? true : false
122134
123135 regridder = XESMF. Regridder (src_coordinates, dst_coordinates; method, periodic)
@@ -155,7 +167,7 @@ llg = LatitudeLongitudeGrid(; size=(360, 180, 1), z,
155167src_field = CenterField(tg)
156168dst_field = CenterField(llg)
157169
158- λ₀, φ₀ = 150, 30. # degrees
170+ λ₀, φ₀ = 150, 30 # degrees
159171width = 12 # degrees
160172set!(src_field, (λ, φ, z) -> exp(-((λ - λ₀)^2 + (φ - φ₀)^2) / 2width^2))
161173
0 commit comments