Skip to content

Commit 3c58432

Browse files
committed
fix CMIP remapping
1 parent bc09a95 commit 3c58432

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

experiments/ClimaEarth/components/ocean/climaocean_helpers.jl

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,36 @@ care about the surface.
99
@inline to_node(pt::CC.Geometry.LatLongZPoint) = pt.long, pt.lat, zero(pt.lat)
1010

1111
"""
12-
map_interpolate(points, oc_field::OC.Field)
12+
map_interpolate!(target_field::CC.Fields.Field, source_field::OC.Field)
1313
14-
Interpolate the given 3D field onto the target points.
14+
Interpolate the given 3D field onto the target field, modifying the target field in place.
1515
16-
If the underlying grid does not contain a given point, return 0 instead.
16+
If the underlying grid does not contain a given point, writes 0 instead.
1717
18-
Note: `map_interpolate` does not support interpolation from `Field`s defined on
18+
Note: `map_interpolate!` does not support interpolation from `Field`s defined on
1919
`OrthogononalSphericalShellGrids` such as the `TripolarGrid`.
20-
21-
TODO: Use a non-allocating version of this function (simply replace `map` with `map!`)
2220
"""
23-
function map_interpolate(points, oc_field::OC.Field)
24-
loc = map(L -> L(), OC.Fields.location(oc_field))
25-
grid = oc_field.grid
26-
data = oc_field.data
21+
function map_interpolate!(target_field::CC.Fields.Field, source_field::OC.Field)
22+
points = CC.Fields.coordinate_field(axes(target_field))
23+
loc = map(L -> L(), OC.Fields.location(source_field))
24+
grid = source_field.grid
25+
data = source_field.data
2726

2827
# TODO: There has to be a better way
2928
min_lat, max_lat = extrema(OC.φnodes(grid, OC.Center(), OC.Center(), OC.Center()))
3029

31-
map(points) do pt
30+
# Use map! on the field directly, which handles complex data layouts correctly
31+
map!(target_field, points) do pt
3232
FT = eltype(pt)
3333

3434
# The oceananigans grid does not cover the entire globe, so we should not
3535
# interpolate outside of its latitude bounds. Instead we return 0
3636
min_lat < pt.lat < max_lat || return FT(0)
3737

3838
fᵢ = OC.Fields.interpolate(to_node(pt), data, loc, grid)
39-
convert(FT, fᵢ)::FT
39+
return convert(FT, fᵢ)::FT
4040
end
41+
return nothing
4142
end
4243

4344
"""
@@ -54,14 +55,33 @@ function surface_flux(f::OC.AbstractField)
5455
end
5556
end
5657

57-
function Interfacer.remap(field::OC.Field, target_space)
58-
return map_interpolate(CC.Fields.coordinate_field(target_space), field)
58+
function Interfacer.remap!(target_field::CC.Fields.Field, source_field::OC.Field)
59+
map_interpolate!(target_field, source_field)
60+
return nothing
5961
end
6062

61-
function Interfacer.remap(operation::OC.AbstractOperations.AbstractOperation, target_space)
63+
function Interfacer.remap!(
64+
target_field::CC.Fields.Field,
65+
operation::OC.AbstractOperations.AbstractOperation,
66+
)
6267
evaluated_field = OC.Field(operation)
6368
OC.compute!(evaluated_field)
64-
return Interfacer.remap(evaluated_field, target_space)
69+
Interfacer.remap!(target_field, evaluated_field)
70+
return nothing
71+
end
72+
73+
function Interfacer.remap(target_space, field::OC.Field)
74+
# Allocate target field and call remap!
75+
target_field = CC.Fields.zeros(target_space)
76+
Interfacer.remap!(target_field, field)
77+
return target_field
78+
end
79+
80+
function Interfacer.remap(target_space, operation::OC.AbstractOperations.AbstractOperation)
81+
# Allocate target field and call remap!
82+
target_field = CC.Fields.zeros(target_space)
83+
Interfacer.remap!(target_field, operation)
84+
return target_field
6585
end
6686

6787
"""

0 commit comments

Comments
 (0)