Skip to content

Commit 10b2abb

Browse files
committed
fixes
1 parent ce3f197 commit 10b2abb

File tree

2 files changed

+91
-35
lines changed

2 files changed

+91
-35
lines changed

experiments/ClimaEarth/components/ocean/climaocean_helpers.jl

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,44 @@ function surface_flux(f::OC.AbstractField)
1414
end
1515
end
1616

17-
function Interfacer.remap(operation::OC.AbstractOperations.AbstractOperation, target_space)
17+
function Interfacer.remap(
18+
operation::OC.AbstractOperations.AbstractOperation,
19+
remapping,
20+
target_space,
21+
)
22+
evaluated_field = OC.Field(operation)
23+
OC.compute!(evaluated_field)
24+
return Interfacer.remap(evaluated_field, remapping, target_space)
25+
end
26+
27+
function Interfacer.remap!(
28+
target_field,
29+
operation::OC.AbstractOperations.AbstractOperation,
30+
remapping,
31+
)
1832
evaluated_field = OC.Field(operation)
1933
OC.compute!(evaluated_field)
20-
return Interfacer.remap(evaluated_field, target_space)
34+
return Interfacer.remap!(target_field, evaluated_field, remapping)
35+
end
36+
37+
# Handle the case when remap is called on an operation without remapping argument
38+
# This happens when the generic remap! calls remap(source, target_space)
39+
# This should not happen for Oceananigans - operations always need remapping
40+
function Interfacer.remap(operation::OC.AbstractOperations.AbstractOperation, target_space)
41+
error(
42+
"Cannot remap Oceananigans AbstractOperation to target space without remapping object. " *
43+
"Use the specialized get_field! method for OceananigansSimulation instead.",
44+
)
45+
end
46+
47+
# Handle the case when remap is called on an Oceananigans Field without remapping argument
48+
# This happens when the generic remap! calls remap(source, target_space)
49+
function Interfacer.remap(src_field::OC.Field, target_space)
50+
error(
51+
"Cannot remap Oceananigans Field to target space without remapping object. " *
52+
"Oceananigans Fields require a remapping object to convert to ClimaCore spaces. " *
53+
"Use the specialized get_field! method for OceananigansSimulation instead.",
54+
)
2155
end
2256

2357
"""
@@ -108,11 +142,11 @@ function compute_cell_matrix(
108142
FT = eltype(grid)
109143

110144
vertices_per_cell = 5 # convention: [sw, nw, ne, se, sw]
111-
ArrayType = Oceananigans.Architectures.array_type(arch)
145+
ArrayType = OC.Architectures.array_type(arch)
112146
cell_matrix = ArrayType{Tuple{FT, FT}}(undef, vertices_per_cell, Fx * Fy)
113147

114148
arch = grid.architecture
115-
Oceananigans.Utils.launch!(
149+
OC.Utils.launch!(
116150
arch,
117151
grid,
118152
(Fx, Fy),
@@ -127,13 +161,13 @@ function compute_cell_matrix(
127161
return cell_matrix
128162
end
129163

130-
flip(::Face) = Center()
131-
flip(::Center) = Face()
164+
flip(::OC.Face) = OC.Center()
165+
flip(::OC.Center) = OC.Face()
132166

133-
left_index(i, ::Center) = i
134-
left_index(i, ::Face) = i - 1
135-
right_index(i, ::Center) = i + 1
136-
right_index(i, ::Face) = i
167+
left_index(i, ::OC.Center) = i
168+
left_index(i, ::OC.Face) = i - 1
169+
right_index(i, ::OC.Center) = i + 1
170+
right_index(i, ::OC.Face) = i
137171

138172
@kernel function _compute_cell_matrix!(cell_matrix, Fx, ℓx, ℓy, grid)
139173
i, j = @index(Global, NTuple)
@@ -153,17 +187,17 @@ right_index(i, ::Face) = i
153187
ise = right_index(i, ℓx)
154188
jse = left_index(j, ℓy)
155189

156-
xsw = ξnode(isw, jsw, 1, grid, vx, vy, nothing)
157-
ysw = ηnode(isw, jsw, 1, grid, vx, vy, nothing)
190+
xsw = OC.ξnode(isw, jsw, 1, grid, vx, vy, nothing)
191+
ysw = OC.ηnode(isw, jsw, 1, grid, vx, vy, nothing)
158192

159-
xnw = ξnode(inw, jnw, 1, grid, vx, vy, nothing)
160-
ynw = ηnode(inw, jnw, 1, grid, vx, vy, nothing)
193+
xnw = OC.ξnode(inw, jnw, 1, grid, vx, vy, nothing)
194+
ynw = OC.ηnode(inw, jnw, 1, grid, vx, vy, nothing)
161195

162-
xne = ξnode(ine, jne, 1, grid, vx, vy, nothing)
163-
yne = ηnode(ine, jne, 1, grid, vx, vy, nothing)
196+
xne = OC.ξnode(ine, jne, 1, grid, vx, vy, nothing)
197+
yne = OC.ηnode(ine, jne, 1, grid, vx, vy, nothing)
164198

165-
xse = ξnode(ise, jse, 1, grid, vx, vy, nothing)
166-
yse = ηnode(ise, jse, 1, grid, vx, vy, nothing)
199+
xse = OC.ξnode(ise, jse, 1, grid, vx, vy, nothing)
200+
yse = OC.ηnode(ise, jse, 1, grid, vx, vy, nothing)
167201

168202
linear_idx = i + (j - 1) * Fx
169203
@inbounds begin

experiments/ClimaEarth/components/ocean/oceananigans.jl

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import Oceananigans as OC
22
import ClimaOcean as CO
33
import ClimaCoupler: Checkpointer, FieldExchanger, FluxCalculator, Interfacer, Utilities
4-
import Interfacer: remap, remap!, get_field
4+
import ClimaCoupler.Interfacer: remap, remap!, get_field
55
import ClimaComms
66
import ClimaCore as CC
77
import Thermodynamics as TD
88
import ClimaParams as CP
99
import ClimaOcean.EN4: download_dataset
1010
using KernelAbstractions: @kernel, @index, @inbounds
11-
import ConservativeRemapping as CR
11+
import ConservativeRegridding as CR
1212

1313
include("climaocean_helpers.jl")
1414

@@ -76,7 +76,7 @@ function OceananigansSimulation(
7676
bottom_height = CO.regrid_bathymetry(
7777
underlying_grid;
7878
minimum_depth = 30,
79-
interpolation_passes = 20,
79+
interpolation_passes = 1,
8080
major_basins = 1,
8181
)
8282
grid = OC.ImmersedBoundaryGrid(
@@ -183,7 +183,7 @@ To regrid from ClimaCore to Oceananigans, use `CR.regrid!(dest_vector, transpose
183183
"""
184184
function construct_remappers(grid_oc, boundary_space)
185185
# Get the vector of polygons for Oceananigans and ClimaCore spaces
186-
vertices_oc = compute_cell_matrix(grid_oc)
186+
vertices_oc = compute_cell_matrix(grid_oc.underlying_grid)
187187
vertices_cc = CC.Remapping.get_element_vertices(boundary_space)
188188

189189
remapper_oc_to_cc = CR.Regridder(vertices_cc, vertices_oc)
@@ -210,12 +210,15 @@ end
210210

211211
# Non-allocating ClimaCore -> Oceananigans remap
212212
function Interfacer.remap!(dst_field::OC.Field, src_field::CC.Fields.Field, remapping)
213-
value_per_element_cc =
214-
CC.Remappping.get_value_per_element(src_field, remapping.field_ones_cc)
213+
CC.Remapping.get_value_per_element!(
214+
remapping.value_per_element_cc,
215+
src_field,
216+
remapping.field_ones_cc,
217+
)
215218
CR.regrid!(
216-
vec(interior(dst_field)),
219+
vec(OC.interior(dst_field, :, :, 1)),
217220
transpose(remapping.remapper_oc_to_cc),
218-
value_per_element_cc,
221+
remapping.value_per_element_cc,
219222
)
220223
return nothing
221224
end
@@ -235,13 +238,18 @@ function Interfacer.remap!(dst_field::CC.Fields.Field, src_field::OC.Field, rema
235238
CR.regrid!(
236239
remapping.value_per_element_cc,
237240
remapping.remapper_oc_to_cc,
238-
vec(interior(src_field)),
241+
vec(OC.interior(src_field, :, :, 1)),
239242
)
240243

241244
# Convert the vector of remapped values to a ClimaCore Field with one value per element
242245
CC.Remapping.set_value_per_element!(dst_field, remapping.value_per_element_cc)
243246
return nothing
244247
end
248+
# Handle the case of remapping the area fraction field, which is a ClimaCore Field
249+
Interfacer.remap!(dst_field::CC.Fields.Field, src_field::CC.Fields.Field, remapping) =
250+
Interfacer.remap!(dst_field, src_field)
251+
Interfacer.remap!(dst_field::CC.Fields.Field, src_field::Number, remapping) =
252+
Interfacer.remap!(dst_field, src_field)
245253
# Allocating Oceananigans -> ClimaCore remap
246254
function Interfacer.remap(
247255
src_field::OC.Field,
@@ -253,10 +261,22 @@ function Interfacer.remap(
253261
return dst_field
254262
end
255263

264+
# Handle the case of remapping a scalar number to a ClimaCore space
265+
Interfacer.remap(num::Number, remapping, target_space::CC.Spaces.AbstractSpace) =
266+
Interfacer.remap(num, target_space)
267+
256268
# Extend Interfacer.get_field to allow automatic remapping to the target space
257269
# TODO see if we can remove this
258-
function Interfacer.get_field(sim, quantity, target_space)
259-
return remap(Interfacer.get_field(sim, quantity), sim.remapping, target_space)
270+
function Interfacer.get_field(sim::OceananigansSimulation, quantity, target_space)
271+
return Interfacer.remap(
272+
Interfacer.get_field(sim, quantity),
273+
sim.remapping,
274+
target_space,
275+
)
276+
end
277+
function Interfacer.get_field!(target_field, sim::OceananigansSimulation, quantity)
278+
Interfacer.remap!(target_field, Interfacer.get_field(sim, quantity), sim.remapping)
279+
return nothing
260280
end
261281

262282
"""
@@ -363,21 +383,23 @@ function FluxCalculator.update_turbulent_fluxes!(sim::OceananigansSimulation, fi
363383
Interfacer.remap!(sim.remapping.scratch_field_oc2, F_turb_ρτyz, sim.remapping) # meridional momentum flux
364384

365385
# Rename for clarity; these are now Center, Center Oceananigans fields
366-
F_turb_ρτxz_oc = OC.interior(sim.remapping.scratch_field_oc1, :, :, 1)
367-
F_turb_ρτyz_oc = OC.interior(sim.remapping.scratch_field_oc2, :, :, 1)
386+
oc_F_turb_ρτxz = sim.remapping.scratch_field_oc1
387+
oc_F_turb_ρτyz = sim.remapping.scratch_field_oc2
368388

369389
# Weight by (1 - sea ice concentration)
370-
OC.interior(F_turb_ρτxz_oc, :, :, 1) .= F_turb_ρτxz_oc .* (1.0 .- ice_concentration)
371-
OC.interior(F_turb_ρτyz_oc, :, :, 1) .= F_turb_ρτyz_oc .* (1.0 .- ice_concentration)
390+
OC.interior(oc_F_turb_ρτxz, :, :, 1) .=
391+
OC.interior(oc_F_turb_ρτxz, :, :, 1) .* (1.0 .- ice_concentration)
392+
OC.interior(oc_F_turb_ρτyz, :, :, 1) .=
393+
OC.interior(oc_F_turb_ρτyz, :, :, 1) .* (1.0 .- ice_concentration)
372394

373395
# Set the momentum flux BCs at the correct locations using the remapped scratch fields
374396
oc_flux_u = surface_flux(sim.ocean.model.velocities.u)
375397
oc_flux_v = surface_flux(sim.ocean.model.velocities.v)
376398
set_from_extrinsic_vector!(
377399
(; u = oc_flux_u, v = oc_flux_v),
378400
grid,
379-
F_turb_ρτxz_cc,
380-
F_turb_ρτyz_cc,
401+
oc_F_turb_ρτxz,
402+
oc_F_turb_ρτyz,
381403
)
382404

383405
(; reference_density, heat_capacity, fresh_water_density) = sim.ocean_properties

0 commit comments

Comments
 (0)