-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathclimaocean_helpers.jl
More file actions
104 lines (90 loc) · 3.24 KB
/
climaocean_helpers.jl
File metadata and controls
104 lines (90 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""
surface_flux(f::OC.AbstractField)
Extract the top boundary conditions for the given field.
"""
function surface_flux(f::OC.AbstractField)
top_bc = f.boundary_conditions.top
if top_bc isa OC.BoundaryCondition{<:OC.BoundaryConditions.Flux}
return top_bc.condition
else
return nothing
end
end
"""
set_from_extrinsic_vector!(vector, grid, u_cc, v_cc)
Given the extrinsic vector components `u_cc` and `v_cc` as `Center, Center`
fields, rotate them onto the target grid and remap to `Face, Center` and
`Center, Face` fields, respectively.
"""
function set_from_extrinsic_vector!(vector, grid, u_cc, v_cc)
arch = OC.Architectures.architecture(grid)
# Rotate vector components onto the grid
OC.Utils.launch!(arch, grid, :xy, _rotate_vector!, u_cc, v_cc, grid)
# Fill halo regions with the rotated vector components so we can use them to interpolate
OC.fill_halo_regions!(u_cc)
OC.fill_halo_regions!(v_cc)
# Interpolate the vector components to face/center and center/face respectively
OC.Utils.launch!(
arch,
grid,
:xy,
_interpolate_vector!,
vector.u,
vector.v,
grid,
u_cc,
v_cc,
)
return nothing
end
"""
_rotate_vector!(τx, τy, grid)
Rotate the velocities from the extrinsic coordinate system to the intrinsic
coordinate system.
"""
@kernel function _rotate_vector!(τx, τy, grid)
# Use `k = 1` to index into the reduced Fields
i, j = @index(Global, NTuple)
# Rotate u, v from extrinsic to intrinsic coordinate system
τxr, τyr = OC.Operators.intrinsic_vector(i, j, 1, grid, τx, τy)
@inbounds begin
τx[i, j, 1] = τxr
τy[i, j, 1] = τyr
end
end
"""
_interpolate_vector!(τx, τy, grid, τx_cc, τy_cc)
Interpolate the input fluxes `τx_cc` and `τy_cc`, which are Center/Center
Fields to Face/Center and Center/Face coordinates, respectively.
"""
@kernel function _interpolate_vector!(τx, τy, grid, τx_cc, τy_cc)
# Use `k = 1` to index into the reduced Fields
i, j = @index(Global, NTuple)
@inbounds begin
τx[i, j, 1] = OC.Operators.ℑxᶠᵃᵃ(i, j, 1, grid, τx_cc)
τy[i, j, 1] = OC.Operators.ℑyᵃᶠᵃ(i, j, 1, grid, τy_cc)
end
end
"""
contravariant_to_cartesian!(ρτ_flux_uv, ρτxz, ρτyz)
Convert the covariant vector components `ρτxz` and `ρτyz` from the
contravariant basis (as they are output by the surface flux calculation)
to the Cartesian basis. These are now in an extrinsic coordinate system
that can be rotated onto the ocean/sea ice grid by `_rotate_vector!`.
"""
function contravariant_to_cartesian!(ρτ_flux_uv, ρτxz, ρτyz)
# Get the local geometry of the boundary space
local_geometry = CC.Fields.local_geometry_field(ρτxz)
# Get the vector components in the CT1 and CT2 directions
xz = @. CA.CT12(
CA.CT1(CA.unit_basis_vector_data(CA.CT1, local_geometry)),
local_geometry,
)
yz = @. CA.CT12(
CA.CT2(CA.unit_basis_vector_data(CA.CT2, local_geometry)),
local_geometry,
)
# Convert the vector components to a UVVector on the Cartesian basis
@. ρτ_flux_uv = @. CC.Geometry.UVVector(ρτxz * xz + ρτyz * yz, local_geometry)
return nothing
end