Skip to content

Commit 167eb72

Browse files
authored
Lay the groundwork for prognostic atmospheres (#355)
* Lay the groundwork for prognostic atmospheres * Fix PrescribedAtmosphere time_step! * Bugfix in test_surface_fluxes * Generalize interface for StateExchanger * Omit sync clock
1 parent 16a7ee3 commit 167eb72

File tree

9 files changed

+45
-31
lines changed

9 files changed

+45
-31
lines changed

src/OceanSeaIceModels/InterfaceComputations/atmosphere_ocean_fluxes.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Oceananigans.Operators: intrinsic_vector
22
using Oceananigans.Grids: inactive_node
33
using ClimaOcean.OceanSeaIceModels.PrescribedAtmospheres: thermodynamics_parameters,
4-
reference_height,
4+
surface_layer_height,
55
boundary_layer_height
66

77
function compute_atmosphere_ocean_fluxes!(coupled_model)
@@ -36,7 +36,7 @@ function compute_atmosphere_ocean_fluxes!(coupled_model)
3636
interface_properties = coupled_model.interfaces.atmosphere_ocean_interface.properties
3737
ocean_properties = coupled_model.interfaces.ocean_properties
3838
atmosphere_properties = (thermodynamics_parameters = thermodynamics_parameters(atmosphere),
39-
reference_height = reference_height(atmosphere))
39+
surface_layer_height = surface_layer_height(atmosphere))
4040

4141
kernel_parameters = interface_kernel_parameters(grid)
4242

@@ -96,7 +96,7 @@ end
9696
# ⋅ 𝒰 ≡ "dynamic" state vector (thermodynamics + reference height + velocity)
9797
ℂₐ = atmosphere_properties.thermodynamics_parameters
9898
𝒬ₐ = thermodynamic_atmospheric_state = AtmosphericThermodynamics.PhaseEquil_pTq(ℂₐ, pₐ, Tₐ, qₐ)
99-
zₐ = atmosphere_properties.reference_height # elevation of atmos variables relative to interface
99+
zₐ = atmosphere_properties.surface_layer_height # elevation of atmos variables relative to interface
100100

101101
local_atmosphere_state = (z = zₐ,
102102
u = uₐ,

src/OceanSeaIceModels/InterfaceComputations/atmosphere_sea_ice_fluxes.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function compute_atmosphere_sea_ice_fluxes!(coupled_model)
3939
ocean_properties = coupled_model.interfaces.ocean_properties
4040

4141
atmosphere_properties = (thermodynamics_parameters = atmosphere.thermodynamics_parameters,
42-
reference_height = atmosphere.reference_height)
42+
surface_layer_height = atmosphere.surface_layer_height)
4343

4444
kernel_parameters = interface_kernel_parameters(grid)
4545

@@ -108,7 +108,7 @@ end
108108
# ⋅ 𝒰 ≡ "dynamic" state vector (thermodynamics + reference height + velocity)
109109
ℂₐ = atmosphere_properties.thermodynamics_parameters
110110
𝒬ₐ = thermodynamic_atmospheric_state = AtmosphericThermodynamics.PhaseEquil_pTq(ℂₐ, pₐ, Tₐ, qₐ)
111-
zₐ = atmosphere_properties.reference_height # elevation of atmos variables relative to interface
111+
zₐ = atmosphere_properties.surface_layer_height # elevation of atmos variables relative to interface
112112

113113
local_atmosphere_state = (z = zₐ,
114114
u = uₐ,

src/OceanSeaIceModels/InterfaceComputations/component_interfaces.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ using ..OceanSeaIceModels: reference_density,
1111
freshwater_flux,
1212
SeaIceSimulation
1313

14+
using ..OceanSeaIceModels.PrescribedAtmospheres:
15+
PrescribedAtmosphere,
16+
thermodynamics_parameters
17+
1418
using ClimaSeaIce: SeaIceModel
1519

1620
using Oceananigans: HydrostaticFreeSurfaceModel, architecture
@@ -77,9 +81,12 @@ function StateExchanger(ocean::Simulation, atmosphere)
7781
Qℓ = Field{Center, Center, Nothing}(exchange_grid),
7882
Mp = Field{Center, Center, Nothing}(exchange_grid))
7983

80-
# TODO: use kernel_parameters not hard code?
81-
# kernel_parameters = interface_kernel_parameters(ocean_grid)
82-
84+
exchanger = atmosphere_exchanger(atmosphere, exchange_grid)
85+
86+
return StateExchanger(ocean.model.grid, exchange_atmosphere_state, exchanger)
87+
end
88+
89+
function atmosphere_exchanger(atmosphere::PrescribedAtmosphere, exchange_grid)
8390
atmos_grid = atmosphere.grid
8491
arch = architecture(exchange_grid)
8592
Nx, Ny, Nz = size(exchange_grid)
@@ -97,7 +104,7 @@ function StateExchanger(ocean::Simulation, atmosphere)
97104
launch!(arch, exchange_grid, kernel_parameters,
98105
_compute_fractional_indices!, frac_indices, exchange_grid, atmos_grid)
99106

100-
return StateExchanger(ocean.model.grid, exchange_atmosphere_state, frac_indices)
107+
return frac_indices
101108
end
102109

103110
@kernel function _compute_fractional_indices!(indices_tuple, exchange_grid, atmos_grid)
@@ -263,7 +270,7 @@ function ComponentInterfaces(atmosphere, ocean, sea_ice=nothing;
263270
sea_ice_heat_capacity = convert(FT, sea_ice_heat_capacity)
264271
freshwater_density = convert(FT, freshwater_density)
265272

266-
atmosphere_properties = atmosphere.thermodynamics_parameters
273+
atmosphere_properties = thermodynamics_parameters(atmosphere)
267274

268275
ocean_properties = (reference_density = ocean_reference_density,
269276
heat_capacity = ocean_heat_capacity,

src/OceanSeaIceModels/InterfaceComputations/interpolate_atmospheric_state.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ using Oceananigans.OutputReaders: TimeInterpolator
55

66
using ...OceanSimulations: forcing_barotropic_potential
77

8+
using ClimaOcean.OceanSeaIceModels.PrescribedAtmospheres: PrescribedAtmosphere
9+
import ClimaOcean.OceanSeaIceModels: interpolate_atmosphere_state!
10+
11+
# TODO: move to PrescribedAtmospheres
812
"""Interpolate the atmospheric state onto the ocean / sea-ice grid."""
9-
function interpolate_atmospheric_state!(coupled_model)
13+
function interpolate_atmosphere_state!(interfaces, atmosphere::PrescribedAtmosphere, coupled_model)
1014
ocean = coupled_model.ocean
11-
atmosphere = coupled_model.atmosphere
1215
atmosphere_grid = atmosphere.grid
1316

1417
# Basic model properties

src/OceanSeaIceModels/OceanSeaIceModels.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ sea_ice_concentration(sea_ice::SeaIceSimulation) = sea_ice.model.ice_concentrati
4646
##### Some implementation
4747
#####
4848

49+
# Atmosphere interface
50+
interpolate_atmosphere_state!(interfaces, atmosphere, coupled_model) = nothing
51+
compute_net_atmosphere_fluxes!(coupled_model) = nothing
52+
53+
# TODO: import this last
4954
include("PrescribedAtmospheres.jl")
5055

5156
using .PrescribedAtmospheres:
@@ -73,7 +78,6 @@ compute_atmosphere_ocean_fluxes!(::NoAtmosphereModel) = nothing
7378
compute_atmosphere_sea_ice_fluxes!(::NoAtmosphereModel) = nothing
7479

7580
const PrescribedAtmosphereModel = OceanSeaIceModel{<:Any, <:PrescribedAtmosphere}
76-
7781
compute_net_atmosphere_fluxes!(::PrescribedAtmosphereModel) = nothing
7882

7983
# "No sea ice" implementation

src/OceanSeaIceModels/PrescribedAtmospheres.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using Oceananigans.Grids: grid_name
44
using Oceananigans.Utils: prettysummary, Time
55
using Oceananigans.Fields: Center
66
using Oceananigans.OutputReaders: FieldTimeSeries, update_field_time_series!, extract_field_time_series
7-
using Oceananigans.TimeSteppers: tick!, Clock
7+
using Oceananigans.TimeSteppers: Clock, tick!
88

99
using Adapt
1010
using Thermodynamics.Parameters: AbstractThermodynamicsParameters
@@ -289,7 +289,7 @@ const PATP = PrescribedAtmosphereThermodynamicsParameters
289289
##### Prescribed atmosphere (as opposed to dynamically evolving / prognostic)
290290
#####
291291

292-
struct PrescribedAtmosphere{FT, M, G, T, U, P, C, F, I, R, TP, TI}
292+
mutable struct PrescribedAtmosphere{FT, M, G, T, U, P, C, F, I, R, TP, TI}
293293
grid :: G
294294
clock :: Clock{T}
295295
metadata :: M
@@ -301,7 +301,7 @@ struct PrescribedAtmosphere{FT, M, G, T, U, P, C, F, I, R, TP, TI}
301301
downwelling_radiation :: R
302302
thermodynamics_parameters :: TP
303303
times :: TI
304-
reference_height :: FT
304+
surface_layer_height :: FT
305305
boundary_layer_height :: FT
306306
end
307307

@@ -315,7 +315,7 @@ end
315315
function Base.show(io::IO, pa::PrescribedAtmosphere)
316316
print(io, summary(pa), " on ", grid_name(pa.grid), ":", '\n')
317317
print(io, "├── times: ", prettysummary(pa.times), '\n')
318-
print(io, "├── reference_height: ", prettysummary(pa.reference_height), '\n')
318+
print(io, "├── surface_layer_height: ", prettysummary(pa.surface_layer_height), '\n')
319319
print(io, "└── boundary_layer_height: ", prettysummary(pa.boundary_layer_height))
320320
end
321321

@@ -350,9 +350,9 @@ function default_atmosphere_pressure(grid, times)
350350
return pa
351351
end
352352

353-
@inline function time_step!(atmos::PrescribedAtmosphere, Δt)
353+
@inline function time_step!(atmos::PrescribedAtmosphere, Δt)
354354
tick!(atmos.clock, Δt)
355-
355+
356356
time = Time(atmos.clock.time)
357357
ftses = extract_field_time_series(atmos)
358358

@@ -364,14 +364,14 @@ end
364364
end
365365

366366
@inline thermodynamics_parameters(atmos::PrescribedAtmosphere) = atmos.thermodynamics_parameters
367-
@inline reference_height(atmos::PrescribedAtmosphere) = atmos.reference_height
367+
@inline surface_layer_height(atmos::PrescribedAtmosphere) = atmos.surface_layer_height
368368
@inline boundary_layer_height(atmos::PrescribedAtmosphere) = atmos.boundary_layer_height
369369

370370
"""
371371
PrescribedAtmosphere(grid, times;
372372
clock = Clock{Float64}(time = 0),
373373
metadata = nothing,
374-
reference_height = 10, # meters
374+
surface_layer_height = 10, # meters
375375
boundary_layer_height = 600 # meters,
376376
thermodynamics_parameters = PrescribedAtmosphereThermodynamicsParameters(FT),
377377
auxiliary_freshwater_flux = nothing,
@@ -387,7 +387,7 @@ state with data given at `times`.
387387
function PrescribedAtmosphere(grid, times;
388388
clock = Clock{Float64}(time = 0),
389389
metadata = nothing,
390-
reference_height = convert(eltype(grid), 10),
390+
surface_layer_height = convert(eltype(grid), 10),
391391
boundary_layer_height = convert(eltype(grid), 600),
392392
thermodynamics_parameters = nothing,
393393
auxiliary_freshwater_flux = nothing,
@@ -413,7 +413,7 @@ function PrescribedAtmosphere(grid, times;
413413
downwelling_radiation,
414414
thermodynamics_parameters,
415415
times,
416-
convert(FT, reference_height),
416+
convert(FT, surface_layer_height),
417417
convert(FT, boundary_layer_height))
418418
end
419419

src/OceanSeaIceModels/time_step_ocean_sea_ice_model.jl

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ using .InterfaceComputations:
33
compute_sea_ice_ocean_fluxes!,
44
compute_net_ocean_fluxes!,
55
compute_net_sea_ice_fluxes!,
6-
interpolate_atmospheric_state!
6+
interpolate_atmosphere_state!
77

88
using ClimaSeaIce: SeaIceModel, SeaIceThermodynamics
99
using Oceananigans.Grids: φnode
@@ -14,6 +14,7 @@ function time_step!(coupled_model::OceanSeaIceModel, Δt; callbacks=[], compute_
1414
ocean = coupled_model.ocean
1515
sea_ice = coupled_model.sea_ice
1616
atmosphere = coupled_model.atmosphere
17+
clock = coupled_model.clock
1718

1819
# Be paranoid and update state at iteration 0
1920
coupled_model.clock.iteration == 0 && update_state!(coupled_model, callbacks)
@@ -31,14 +32,12 @@ function time_step!(coupled_model::OceanSeaIceModel, Δt; callbacks=[], compute_
3132
parent(h⁻) .= parent(hⁿ)
3233
end
3334

34-
sea_ice.Δt = Δt
35-
time_step!(sea_ice)
35+
time_step!(sea_ice, Δt)
3636
end
3737

3838
# TODO after ice time-step:
3939
# - Adjust ocean heat flux if the ice completely melts?
40-
ocean.Δt = Δt
41-
time_step!(ocean)
40+
time_step!(ocean, Δt)
4241

4342
# Time step the atmosphere
4443
time_step!(atmosphere, Δt)
@@ -55,7 +54,7 @@ end
5554
function update_state!(coupled_model::OceanSeaIceModel, callbacks=[]; compute_tendencies=true)
5655

5756
# This function needs to be specialized to allow different atmospheric models
58-
interpolate_atmospheric_state!(coupled_model)
57+
interpolate_atmosphere_state!(coupled_model.interfaces, coupled_model.atmosphere, coupled_model)
5958

6059
# Compute interface states
6160
compute_atmosphere_ocean_fluxes!(coupled_model)

src/OceanSimulations/ocean_simulation.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ function ocean_simulation(grid;
105105
boundary_conditions::NamedTuple = NamedTuple(),
106106
tracer_advection = default_tracer_advection(),
107107
vertical_coordinate = default_vertical_coordinate(grid),
108+
warn = true,
108109
verbose = false)
109110

110111
FT = eltype(grid)
@@ -131,7 +132,7 @@ function ocean_simulation(grid;
131132
u_immersed_bc = DefaultBoundaryCondition()
132133
v_immersed_bc = DefaultBoundaryCondition()
133134
else
134-
if !(grid isa ImmersedBoundaryGrid)
135+
if warn && !(grid isa ImmersedBoundaryGrid)
135136
msg = """Are you totally, 100% sure that you want to build a simulation on
136137
137138
$(summary(grid))

test/test_surface_fluxes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ end
4545
atmosphere = JRA55PrescribedAtmosphere(1:2; grid, architecture=arch, backend=InMemory())
4646

4747
CUDA.@allowscalar begin
48-
h = atmosphere.reference_height
48+
h = atmosphere.surface_layer_height
4949
pₐ = atmosphere.pressure[1][1, 1, 1]
5050

5151
Tₐ = atmosphere.tracers.T[1][1, 1, 1]

0 commit comments

Comments
 (0)