|
207 | 207 | Interfacer.step!(sim::OceananigansSimulation, t) = |
208 | 208 | OC.time_step!(sim.ocean, float(t) - sim.ocean.model.clock.time) |
209 | 209 |
|
210 | | -# We always want the surface, so we always set zero(pt.lat) for z |
211 | | -""" |
212 | | - to_node(pt::CA.ClimaCore.Geometry.LatLongPoint) |
213 | | -
|
214 | | -Transform `LatLongPoint` into a tuple (long, lat, 0), where the 0 is needed because we only |
215 | | -care about the surface. |
216 | | -""" |
217 | | -@inline to_node(pt::CA.ClimaCore.Geometry.LatLongPoint) = pt.long, pt.lat, zero(pt.lat) |
218 | | -# This next one is needed if we have "LevelGrid" |
219 | | -@inline to_node(pt::CA.ClimaCore.Geometry.LatLongZPoint) = pt.long, pt.lat, zero(pt.lat) |
220 | | - |
221 | | -""" |
222 | | - map_interpolate(points, oc_field::OC.Field) |
223 | | -
|
224 | | -Interpolate the given 3D field onto the target points. |
225 | | -
|
226 | | -If the underlying grid does not contain a given point, return 0 instead. |
227 | | -
|
228 | | -TODO: Use a non-allocating version of this function (simply replace `map` with `map!`) |
229 | | -""" |
230 | | -function map_interpolate(points, oc_field::OC.Field) |
231 | | - loc = map(L -> L(), OC.Fields.location(oc_field)) |
232 | | - grid = oc_field.grid |
233 | | - data = oc_field.data |
234 | | - |
235 | | - # TODO: There has to be a better way |
236 | | - min_lat, max_lat = extrema(OC.φnodes(grid, OC.Center(), OC.Center(), OC.Center())) |
237 | | - |
238 | | - map(points) do pt |
239 | | - FT = eltype(pt) |
240 | | - |
241 | | - # The oceananigans grid does not cover the entire globe, so we should not |
242 | | - # interpolate outside of its latitude bounds. Instead we return 0 |
243 | | - min_lat < pt.lat < max_lat || return FT(0) |
244 | | - |
245 | | - fᵢ = OC.Fields.interpolate(to_node(pt), data, loc, grid) |
246 | | - convert(FT, fᵢ)::FT |
247 | | - end |
248 | | -end |
249 | | - |
250 | | -""" |
251 | | - surface_flux(f::OC.AbstractField) |
252 | | -
|
253 | | -Extract the top boundary conditions for the given field. |
254 | | -""" |
255 | | -function surface_flux(f::OC.AbstractField) |
256 | | - top_bc = f.boundary_conditions.top |
257 | | - if top_bc isa OC.BoundaryCondition{<:OC.BoundaryConditions.Flux} |
258 | | - return top_bc.condition |
259 | | - else |
260 | | - return nothing |
261 | | - end |
262 | | -end |
263 | | - |
264 | | -function Interfacer.remap(field::OC.Field, target_space) |
265 | | - return map_interpolate(CC.Fields.coordinate_field(target_space), field) |
266 | | -end |
267 | | - |
268 | | -function Interfacer.remap(operation::OC.AbstractOperations.AbstractOperation, target_space) |
269 | | - evaluated_field = OC.Field(operation) |
270 | | - OC.compute!(evaluated_field) |
271 | | - return Interfacer.remap(evaluated_field, target_space) |
272 | | -end |
273 | | - |
274 | 210 | Interfacer.get_field(sim::OceananigansSimulation, ::Val{:area_fraction}) = sim.area_fraction |
275 | 211 |
|
276 | 212 | # TODO: Better values for this |
@@ -375,70 +311,6 @@ function FluxCalculator.update_turbulent_fluxes!(sim::OceananigansSimulation, fi |
375 | 311 | return nothing |
376 | 312 | end |
377 | 313 |
|
378 | | -""" |
379 | | - set_from_extrinsic_vectors!(vectors, grid, u_cc, v_cc) |
380 | | -
|
381 | | -Given the extrinsic vector components `u_cc` and `v_cc` as `Center, Center` |
382 | | -fields, rotate them onto the target grid and remap to `Face, Center` and |
383 | | -`Center, Face` fields, respectively. |
384 | | -""" |
385 | | -function set_from_extrinsic_vectors!(vectors, grid, u_cc, v_cc) |
386 | | - arch = grid.architecture |
387 | | - |
388 | | - # Rotate vectors onto the grid |
389 | | - OC.Utils.launch!(arch, grid, :xy, _rotate_velocities!, u_cc, v_cc, grid) |
390 | | - |
391 | | - # Fill halo regions with the rotated vectors so we can use them to interpolate |
392 | | - OC.fill_halo_regions!(u_cc) |
393 | | - OC.fill_halo_regions!(v_cc) |
394 | | - |
395 | | - # Interpolate the vectors to face/center and center/face respectively |
396 | | - OC.Utils.launch!( |
397 | | - arch, |
398 | | - grid, |
399 | | - :xy, |
400 | | - _interpolate_velocities!, |
401 | | - vectors.u, |
402 | | - vectors.v, |
403 | | - grid, |
404 | | - u_cc, |
405 | | - v_cc, |
406 | | - ) |
407 | | - return nothing |
408 | | -end |
409 | | - |
410 | | -""" |
411 | | - _rotate_velocities!(u, v, grid) |
412 | | -
|
413 | | -Rotate the velocities from the extrinsic coordinate system to the intrinsic |
414 | | -coordinate system. |
415 | | -""" |
416 | | -@kernel function _rotate_velocities!(u, v, grid) |
417 | | - # Use `k = 1` to index into the reduced Fields |
418 | | - i, j = @index(Global, NTuple) |
419 | | - # Rotate u, v from extrinsic to intrinsic coordinate system |
420 | | - ur, vr = OC.Operators.intrinsic_vector(i, j, 1, grid, u, v) |
421 | | - @inbounds begin |
422 | | - u[i, j, 1] = ur |
423 | | - v[i, j, 1] = vr |
424 | | - end |
425 | | -end |
426 | | - |
427 | | -""" |
428 | | - _interpolate_velocities!(u, v, grid, u_cc, v_cc) |
429 | | -
|
430 | | -Interpolate the input velocities `u_cc` and `v_cc`, which are Center/Center |
431 | | -Fields to Face/Center and Center/Face coordinates, respectively. |
432 | | -""" |
433 | | -@kernel function _interpolate_velocities!(u, v, grid, u_cc, v_cc) |
434 | | - # Use `k = 1` to index into the reduced Fields |
435 | | - i, j = @index(Global, NTuple) |
436 | | - @inbounds begin |
437 | | - u[i, j, 1] = OC.Operators.ℑxyᶠᶜᵃ(i, j, 1, grid, u_cc) |
438 | | - v[i, j, 1] = OC.Operators.ℑxyᶜᶠᵃ(i, j, 1, grid, v_cc) |
439 | | - end |
440 | | -end |
441 | | - |
442 | 314 | function Interfacer.update_field!(sim::OceananigansSimulation, ::Val{:area_fraction}, field) |
443 | 315 | sim.area_fraction .= field |
444 | 316 | return nothing |
|
0 commit comments