1
1
2
2
3
- abstract type ArakawaGrid end
3
+ abstract type ArakawaGridCell end
4
4
5
- struct AGrid <: ArakawaGrid
5
+ struct AGridCell <: ArakawaGridCell
6
+ u_pos:: Symbol
7
+ v_pos:: Symbol
6
8
end
7
9
8
- struct BGrid <: ArakawaGrid
10
+ struct BGridCell <: ArakawaGridCell
11
+ u_pos:: Symbol
12
+ v_pos:: Symbol
9
13
end
10
14
11
- struct CGrid <: ArakawaGrid
15
+ struct CGridCell <: ArakawaGridCell
16
+ u_pos:: Symbol
17
+ v_pos:: Symbol
12
18
end
13
19
14
20
15
21
"""
16
- arakawa, uo_pos, vo_pos, uo_relerr, vo_relerr = gridtype(uo_lon, uo_lat, vo_lon, vo_lat , modelgrid)
22
+ arakawa = getarakawagrid(u_lon, u_lat, v_lon, v_lat , modelgrid)
17
23
18
24
Returns the type of the grid (A, B, or C), the grid position of the velocity points,
19
25
and the error of that position relative to the perimeter of the cell.
@@ -43,14 +49,14 @@ The different Arakawa grids recongnized here are:
43
49
where each grid is centered in C.
44
50
Also returns the distances from the velocity points to the grid points.
45
51
"""
46
- function gridtype (uo_lon, uo_lat, vo_lon, vo_lat , modelgrid)
52
+ function getarakawagrid (u_lon, u_lat, v_lon, v_lat , modelgrid)
47
53
48
54
# Unpack modelgrid
49
55
(; lon, lat, lon_vertices, lat_vertices) = modelgrid
50
56
51
57
i = j = 1
52
- uo_point = (uo_lon [i, j], uo_lat [i, j])
53
- vo_point = (vo_lon [i, j], vo_lat [i, j])
58
+ u_point = (u_lon [i, j], u_lat [i, j])
59
+ v_point = (v_lon [i, j], v_lat [i, j])
54
60
55
61
C = (lon[i, j], lat[i, j])
56
62
SW = (lon_vertices[1 , i, j], lat_vertices[1 , i, j])
@@ -64,75 +70,74 @@ function gridtype(uo_lon, uo_lat, vo_lon, vo_lat, modelgrid)
64
70
65
71
cell = (; C, SW, SE, NE, NW, S, N, W, E)
66
72
67
- uo_distances = (; (k => haversine (P, uo_point ) for (k,P) in pairs (cell)). .. )
68
- vo_distances = (; (k => haversine (P, vo_point ) for (k,P) in pairs (cell)). .. )
73
+ u_distances = (; (k => haversine (P, u_point ) for (k,P) in pairs (cell)). .. )
74
+ v_distances = (; (k => haversine (P, v_point ) for (k,P) in pairs (cell)). .. )
69
75
70
- uo_distance, uo_pos = findmin (uo_distances )
71
- vo_distance, vo_pos = findmin (vo_distances )
76
+ u_distance, u_pos = findmin (u_distances )
77
+ v_distance, v_pos = findmin (v_distances )
72
78
73
79
# Arakawa grid type
74
- if uo_pos == vo_pos == :C
75
- arakawa = AGrid ( )
76
- elseif uo_pos == vo_pos && uo_pos ∈ (:NE , :NW , :SE , :SW )
77
- arakawa = BGrid ( )
78
- elseif uo_pos ∈ (:E , :W ) && vo_pos ∈ (:N , :S )
79
- arakawa = CGrid ( )
80
+ if u_pos == v_pos == :C
81
+ arakawa = AGridCell (u_pos, v_pos )
82
+ elseif u_pos == v_pos && u_pos ∈ (:NE , :NW , :SE , :SW )
83
+ arakawa = BGridCell (u_pos, v_pos )
84
+ elseif u_pos ∈ (:E , :W ) && v_pos ∈ (:N , :S )
85
+ arakawa = CGridCell (u_pos, v_pos )
80
86
else
81
87
error (" Unknown Arakawa grid type" )
82
88
end
83
89
84
90
cellperimeter = haversine (SW, SE) + haversine (SE, NE) + haversine (NE, NW) + haversine (NW, SW)
85
- uo_relerr = uo_distance / cellperimeter
86
- vo_relerr = vo_distance / cellperimeter
91
+ relerr = (u_distance + v_distance) / cellperimeter
87
92
88
- return arakawa, uo_pos, vo_pos, uo_relerr, vo_relerr
93
+ relerr > 0.01 && warn (" Relative error in grid positions in $arakawa is $relerr " )
94
+
95
+ return arakawa
89
96
90
97
end
91
98
92
99
"""
93
- uo, uo_lon, uo_lat, vo, vo_lon, vo_lat = interpolateontodefaultCgrid(uo, uo_lon, uo_lat, vo, vo_lon, vo_lat , modelgrid)
100
+ u, u_lon, u_lat, v, v_lon, v_lat = interpolateontodefaultCgrid(u, u_lon, u_lat, v, v_lon, v_lat , modelgrid)
94
101
95
- Interpolates the velocity fields `uo ` and `vo ` from B- or C-grid
102
+ Interpolates the velocity fields `u ` and `v ` from B- or C-grid
96
103
onto the default C-grid (centered on the cell faces).
97
104
"""
98
- interpolateontodefaultCgrid (uo, uo_lon, uo_lat, vo, vo_lon, vo_lat, modelgrid) = interpolateontodefaultCgrid (uo, uo_lon, uo_lat, vo, vo_lon, vo_lat, modelgrid, gridtype (uo_lon, uo_lat, vo_lon, vo_lat, modelgrid))
99
- interpolateontodefaultCgrid (uo, uo_lon, uo_lat, vo, vo_lon, vo_lat, modelgrid, :: CGrid ) = uo, uo_lon, uo_lat, vo, vo_lon, vo_lat
100
- interpolateontodefaultCgrid (uo, uo_lon, uo_lat, vo, vo_lon, vo_lat, modelgrid, :: AGrid ) = error (" Interpolation not implemented for this grid type" )
101
- # TODO this is clumsy to have to pass the gridtype but then recompute it
102
- function interpolateontodefaultCgrid (uo, uo_lon, uo_lat, vo, vo_lon, vo_lat, modelgrid, arakawa:: BGrid )
103
-
104
- arakawa, uo_pos, vo_pos, uo_relerr, vo_relerr = gridtype (uo_lon, uo_lat, vo_lon, vo_lat, modelgrid)
105
+ interpolateontodefaultCgrid (u, u_lon, u_lat, v, v_lon, v_lat, modelgrid) = interpolateontodefaultCgrid (u, u_lon, u_lat, v, v_lon, v_lat, modelgrid, getarakawagrid (u_lon, u_lat, v_lon, v_lat, modelgrid))
106
+ interpolateontodefaultCgrid (u, u_lon, u_lat, v, v_lon, v_lat, modelgrid, :: CGridCell ) = u, u_lon, u_lat, v, v_lon, v_lat
107
+ interpolateontodefaultCgrid (u, u_lon, u_lat, v, v_lon, v_lat, modelgrid, :: AGridCell ) = error (" Interpolation not implemented for A-grid type" )
108
+ function interpolateontodefaultCgrid (u, u_lon, u_lat, v, v_lon, v_lat, modelgrid, arakawa:: BGridCell )
105
109
106
- uo_pos == vo_pos == :NE || error (" Interpolation not implemented for this B-grid type" )
110
+ (; u_pos, v_pos) = arakawa
111
+ u_pos == v_pos == :NE || error (" Interpolation not implemented for this B-grid($u_pos ,$v_pos ) type" )
107
112
108
- _FillValue = uo . properties[" _FillValue" ]
113
+ _FillValue = u . properties[" _FillValue" ]
109
114
110
- # Make sure uo and vo are in memory
111
- uo = uo |> Array
112
- vo = vo |> Array
115
+ # Make sure u and v are in memory
116
+ u = u |> Array
117
+ v = v |> Array
113
118
114
- nx, ny, nz = size (uo )
119
+ nx, ny, nz = size (u )
115
120
116
121
# unpack modelgrid
117
122
(; lon_vertices, lat_vertices) = modelgrid
118
123
119
- # It seems that uo/vo is NaN on boundaries (for ACCESS-ESM1-5)
120
- # and that umo/vmo were computed as if uo/vo were 0 on boundaries
124
+ # It seems that u/v is NaN on boundaries (for ACCESS-ESM1-5)
125
+ # and that umo/vmo were computed as if u/v were 0 on boundaries
121
126
# so that's what we do here
122
- uo2 = replace (uo , _FillValue => 0.0 )
123
- vo2 = replace (vo , _FillValue => 0.0 )
124
- uo2 = 0.5 (uo2 + [fill (0.0 , nx, 1 , nz);; uo2 [:, 1 : end - 1 , :]])
125
- vo2 = 0.5 (vo2 + [fill (0.0 , 1 , ny, nz); vo2 [1 : end - 1 , :, :]])
127
+ u2 = replace (u , _FillValue => 0.0 )
128
+ v2 = replace (v , _FillValue => 0.0 )
129
+ u2 = 0.5 (u2 + [fill (0.0 , nx, 1 , nz);; u2 [:, 1 : end - 1 , :]])
130
+ v2 = 0.5 (v2 + [fill (0.0 , 1 , ny, nz); v2 [1 : end - 1 , :, :]])
126
131
SE_points = [(lon, lat) for (lon, lat) in zip (lon_vertices[2 , :, :], lat_vertices[2 , :, :])]
127
132
NE_points = [(lon, lat) for (lon, lat) in zip (lon_vertices[3 , :, :], lat_vertices[3 , :, :])]
128
133
NW_points = [(lon, lat) for (lon, lat) in zip (lon_vertices[4 , :, :], lat_vertices[4 , :, :])]
129
- uo2_points = [midpointonsphere (SE, NE) for (SE, NE) in zip (NE_points, SE_points)]
130
- vo2_points = [midpointonsphere (NE, NW) for (NE, NW) in zip (NW_points, NE_points)]
131
- uo2_lon = [P[1 ] for P in uo2_points ]
132
- uo2_lat = [P[2 ] for P in uo2_points ]
133
- vo2_lon = [P[1 ] for P in vo2_points ]
134
- vo2_lat = [P[2 ] for P in vo2_points ]
135
- return uo2, uo2_lon, uo2_lat, vo2, vo2_lon, vo2_lat
134
+ u2_points = [midpointonsphere (SE, NE) for (SE, NE) in zip (NE_points, SE_points)]
135
+ v2_points = [midpointonsphere (NE, NW) for (NE, NW) in zip (NW_points, NE_points)]
136
+ u2_lon = [P[1 ] for P in u2_points ]
137
+ u2_lat = [P[2 ] for P in u2_points ]
138
+ v2_lon = [P[1 ] for P in v2_points ]
139
+ v2_lat = [P[2 ] for P in v2_points ]
140
+ return u2, u2_lon, u2_lat, v2, v2_lon, v2_lat
136
141
137
142
end
138
143
0 commit comments