Skip to content

Commit 9f811df

Browse files
authored
Merge branch 'main' into ts/checkpointer-for-coupled-model
2 parents cfba574 + 83c4d9d commit 9f811df

File tree

7 files changed

+90
-50
lines changed

7 files changed

+90
-50
lines changed

experiments/arctic_simulation.jl

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ using Oceananigans.Units
66
using Oceananigans.OrthogonalSphericalShellGrids
77
using ClimaOcean.OceanSimulations
88
using ClimaOcean.ECCO
9-
using ClimaOcean.ECCO: all_ECCO_dates
9+
using ClimaOcean.DataWrangling
1010
using ClimaSeaIce.SeaIceThermodynamics: IceWaterThermalEquilibrium
1111
using Printf
1212

1313
using CUDA
1414
CUDA.device!(1)
15+
arch = GPU()
1516

1617
r_faces = ClimaOcean.exponential_z_faces(; Nz=30, h=10, depth=2000)
1718
z_faces = MutableVerticalDiscretization(r_faces)
@@ -20,13 +21,13 @@ Nx = 180 # longitudinal direction -> 250 points is about 1.5ᵒ resolution
2021
Ny = 180 # meridional direction -> same thing, 48 points is about 1.5ᵒ resolution
2122
Nz = length(r_faces) - 1
2223

23-
grid = RotatedLatitudeLongitudeGrid(GPU(), size = (Nx, Ny, Nz),
24-
latitude = (-45, 45),
25-
longitude = (-45, 45),
26-
z = r_faces,
27-
north_pole = (180, 0),
28-
halo = (5, 5, 4),
29-
topology = (Bounded, Bounded, Bounded))
24+
grid = RotatedLatitudeLongitudeGrid(arch, size = (Nx, Ny, Nz),
25+
latitude = (-45, 45),
26+
longitude = (-45, 45),
27+
z = r_faces,
28+
north_pole = (180, 0),
29+
halo = (5, 5, 4),
30+
topology = (Bounded, Bounded, Bounded))
3031

3132
bottom_height = regrid_bathymetry(grid; minimum_depth=15, major_basins=1)
3233

@@ -49,27 +50,47 @@ ocean = ocean_simulation(grid;
4950
free_surface,
5051
closure)
5152

52-
set!(ocean.model, T=ECCOMetadata(:temperature),
53-
S=ECCOMetadata(:salinity))
53+
dataset = ECCO4Monthly()
54+
55+
set!(ocean.model, T=Metadata(:temperature; dataset),
56+
S=Metadata(:salinity; dataset))
5457

5558
#####
5659
##### A Prognostic Sea-ice model
5760
#####
5861

62+
using ClimaSeaIce.SeaIceMomentumEquations
63+
using ClimaSeaIce.Rheologies
64+
5965
# Remember to pass the SSS as a bottom bc to the sea ice!
6066
SSS = view(ocean.model.tracers.S, :, :, grid.Nz)
6167
bottom_heat_boundary_condition = IceWaterThermalEquilibrium(SSS)
6268

63-
sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition, dynamics=nothing, advection=nothing)
69+
SSU = view(ocean.model.velocities.u, :, :, grid.Nz)
70+
SSV = view(ocean.model.velocities.u, :, :, grid.Nz)
71+
72+
τo = SemiImplicitStress(uₑ=SSU, vₑ=SSV)
73+
τua = Field{Face, Center, Nothing}(grid)
74+
τva = Field{Center, Face, Nothing}(grid)
75+
76+
dynamics = SeaIceMomentumEquation(grid;
77+
coriolis = ocean.model.coriolis,
78+
top_momentum_stress = (u=τua, v=τva),
79+
bottom_momentum_stress = τo,
80+
ocean_velocities = (u=SSU, v=SSV),
81+
rheology = ElastoViscoPlasticRheology(),
82+
solver = SplitExplicitSolver(120))
83+
84+
sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition, dynamics, advection=WENO(order=7))
6485

65-
set!(sea_ice.model, h=ECCOMetadata(:sea_ice_thickness),
66-
=ECCOMetadata(:sea_ice_concentration))
86+
set!(sea_ice.model, h=Metadata(:sea_ice_thickness; dataset),
87+
=Metadata(:sea_ice_concentration; dataset))
6788

6889
#####
6990
##### A Prescribed Atmosphere model
7091
#####
7192

72-
atmosphere = JRA55PrescribedAtmosphere(GPU(); backend=JRA55NetCDFBackend(40))
93+
atmosphere = JRA55PrescribedAtmosphere(arch; backend=JRA55NetCDFBackend(40))
7394
radiation = Radiation()
7495

7596
#####
@@ -80,10 +101,10 @@ arctic = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation)
80101
arctic = Simulation(arctic, Δt=5minutes, stop_time=365days)
81102

82103
# Sea-ice variables
83-
h = sea_ice.model.ice_thickness
84-
= sea_ice.model.ice_concentration
85-
Gh = sea_ice.model.timestepper.Gⁿ.h
86-
Gℵ = sea_ice.model.timestepper.Gⁿ.
104+
h = sea_ice.model.ice_thickness
105+
= sea_ice.model.ice_concentration
106+
u = sea_ice.model.velocities.u
107+
v = sea_ice.model.velocities.v
87108

88109
# Fluxes
89110
Tu = arctic.model.interfaces.atmosphere_sea_ice_interface.temperature
@@ -93,14 +114,16 @@ Qⁱ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.interface_heat
93114
Qᶠ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.frazil_heat
94115
Qᵗ = arctic.model.interfaces.net_fluxes.sea_ice_top.heat
95116
Qᴮ = arctic.model.interfaces.net_fluxes.sea_ice_bottom.heat
117+
τx = arctic.model.interfaces.net_fluxes.sea_ice_top.u
118+
τy = arctic.model.interfaces.net_fluxes.sea_ice_top.v
96119

97120
# Output writers
98-
arctic.output_writers[:vars] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Gh, Gℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ),
121+
arctic.output_writers[:vars] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, u, v, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ, τx, τy),
99122
filename = "sea_ice_quantities.jld2",
100123
schedule = IterationInterval(12),
101124
overwrite_existing=true)
102125

103-
arctic.output_writers[:avrages] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ),
126+
arctic.output_writers[:averages] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ, u, v, τx, τy),
104127
filename = "averaged_sea_ice_quantities.jld2",
105128
schedule = AveragedTimeInterval(1days),
106129
overwrite_existing=true)
@@ -142,11 +165,11 @@ run!(arctic)
142165
##### Comparison to ECCO Climatology
143166
#####
144167

145-
version = ECCO4Monthly()
146-
dates = all_ECCO_dates(version)[1:12]
168+
dataset = ECCO4Monthly()
169+
dates = all_dates(version)[1:12]
147170

148-
h_metadata = ECCOMetadata(:sea_ice_thickness; version, dates)
149-
ℵ_metadata = ECCOMetadata(:sea_ice_concentration; version, dates)
171+
h_metadata = Metadata(:sea_ice_thickness; dataset, dates)
172+
ℵ_metadata = Metadata(:sea_ice_concentration; dataset, dates)
150173

151174
# Montly averaged ECCO data
152175
hE = ECCOFieldTimeSeries(h_metadata, grid; time_indices_in_memory=12)

src/DataWrangling/ECCO/ECCO_metadata.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,6 @@ function download_dataset(metadata::ECCOMetadata; url = urls(metadata))
168168
# Write down the username and password in a .netrc file
169169
downloader = netrc_downloader(username, password, "ecco.jpl.nasa.gov", tmp)
170170
ntasks = Threads.nthreads()
171-
172-
missing_files = false
173171

174172
asyncmap(metadata; ntasks) do metadatum # Distribute the download among tasks
175173

@@ -194,10 +192,6 @@ function download_dataset(metadata::ECCOMetadata; url = urls(metadata))
194192
Downloads.download(fileurl, filepath; downloader, progress=download_progress)
195193
end
196194
end
197-
198-
if !missing_files
199-
@info "Note: ECCO $(metadata.name) data is in $(metadata.dir)."
200-
end
201195
end
202196

203197
return nothing

src/OceanSeaIceModels/InterfaceComputations/assemble_net_fluxes.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ function compute_net_sea_ice_fluxes!(coupled_model)
154154
arch = architecture(grid)
155155
clock = coupled_model.clock
156156

157-
top_heat_flux = coupled_model.interfaces.net_fluxes.sea_ice_top.heat
157+
top_fluxes = coupled_model.interfaces.net_fluxes.sea_ice_top
158158
bottom_heat_flux = coupled_model.interfaces.net_fluxes.sea_ice_bottom.heat
159159
sea_ice_ocean_fluxes = coupled_model.interfaces.sea_ice_ocean_interface.fluxes
160160
atmosphere_sea_ice_fluxes = coupled_model.interfaces.atmosphere_sea_ice_interface.fluxes
@@ -173,11 +173,11 @@ function compute_net_sea_ice_fluxes!(coupled_model)
173173

174174
kernel_parameters = interface_kernel_parameters(grid)
175175

176-
sea_ice_surface_temperature = coupled_model.interfaces.atmosphere_ocean_interface.temperature
176+
sea_ice_surface_temperature = coupled_model.interfaces.atmosphere_sea_ice_interface.temperature
177177

178178
launch!(arch, grid, kernel_parameters,
179179
_assemble_net_sea_ice_fluxes!,
180-
top_heat_flux,
180+
top_fluxes,
181181
bottom_heat_flux,
182182
grid,
183183
clock,
@@ -192,7 +192,7 @@ function compute_net_sea_ice_fluxes!(coupled_model)
192192
return nothing
193193
end
194194

195-
@kernel function _assemble_net_sea_ice_fluxes!(top_heat_flux,
195+
@kernel function _assemble_net_sea_ice_fluxes!(top_fluxes,
196196
bottom_heat_flux,
197197
grid,
198198
clock,
@@ -220,6 +220,9 @@ end
220220
Qi = sea_ice_ocean_fluxes.interface_heat[i, j, 1] # interfacial heat flux
221221
end
222222

223+
ρτx = atmosphere_sea_ice_fluxes.x_momentum # zonal momentum flux
224+
ρτy = atmosphere_sea_ice_fluxes.y_momentum # meridional momentum flux
225+
223226
# Compute radiation fluxes
224227
σ = atmos_sea_ice_properties.radiation.σ
225228
α = stateindex(atmos_sea_ice_properties.radiation.α, i, j, kᴺ, grid, time)
@@ -233,6 +236,8 @@ end
233236
# Mask fluxes over land for convenience
234237
inactive = inactive_node(i, j, kᴺ, grid, c, c, c)
235238

236-
@inbounds top_heat_flux[i, j, 1] = ifelse(inactive, zero(grid), ΣQt)
239+
@inbounds top_fluxes.heat[i, j, 1] = ifelse(inactive, zero(grid), ΣQt)
240+
@inbounds top_fluxes.u[i, j, 1] = ifelse(inactive, zero(grid), ℑxᶠᵃᵃ(i, j, 1, grid, ρτx))
241+
@inbounds top_fluxes.v[i, j, 1] = ifelse(inactive, zero(grid), ℑyᵃᶠᵃ(i, j, 1, grid, ρτy))
237242
@inbounds bottom_heat_flux[i, j, 1] = ifelse(inactive, zero(grid), ΣQb)
238243
end

src/OceanSeaIceModels/InterfaceComputations/component_interfaces.jl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,7 @@ function ComponentInterfaces(atmosphere, ocean, sea_ice=nothing;
266266
radiation = Radiation(),
267267
freshwater_density = 1000,
268268
atmosphere_ocean_flux_formulation = SimilarityTheoryFluxes(eltype(ocean.model.grid)),
269-
atmosphere_sea_ice_flux_formulation = CoefficientBasedFluxes(drag_coefficient=2e-3,
270-
heat_transfer_coefficient=1e-4,
271-
vapor_flux_coefficient=1e-4),
269+
atmosphere_sea_ice_flux_formulation = SimilarityTheoryFluxes(eltype(ocean.model.grid)),
272270
atmosphere_ocean_interface_temperature = BulkTemperature(),
273271
atmosphere_ocean_velocity_difference = RelativeVelocity(),
274272
atmosphere_ocean_interface_specific_humidity = default_ao_specific_humidity(ocean),
@@ -319,7 +317,17 @@ function ComponentInterfaces(atmosphere, ocean, sea_ice=nothing;
319317
liquidus = sea_ice.model.ice_thermodynamics.phase_transitions.liquidus,
320318
temperature_units = sea_ice_temperature_units)
321319

322-
net_top_sea_ice_fluxes = (; heat=sea_ice.model.external_heat_fluxes.top)
320+
net_momentum_fluxes = if sea_ice.model.dynamics isa Nothing
321+
u = Field{Face, Center, Nothing}(sea_ice.model.grid)
322+
v = Field{Center, Face, Nothing}(sea_ice.model.grid)
323+
(; u, v)
324+
else
325+
u = sea_ice.model.dynamics.external_momentum_stresses.top.u
326+
v = sea_ice.model.dynamics.external_momentum_stresses.top.v
327+
(; u, v)
328+
end
329+
330+
net_top_sea_ice_fluxes = merge((; heat=sea_ice.model.external_heat_fluxes.top), net_momentum_fluxes)
323331
net_bottom_sea_ice_fluxes = (; heat=sea_ice.model.external_heat_fluxes.bottom)
324332
else
325333
sea_ice_properties = nothing

src/OceanSeaIceModels/InterfaceComputations/interface_states.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ end
214214
h = Ψᵢ.h
215215

216216
# Bottom temperature at the melting temperature
217-
Tᵢ = ClimaSeaIce.SeaIceThermodynamics.melting_temperature(ℙᵢ.liquidus, Ψᵢ.S)
218-
Tᵢ = convert_to_kelvin(ℙᵢ.temperature_units, Tᵢ)
217+
Tᵢ = ClimaSeaIce.SeaIceThermodynamics.melting_temperature(ℙᵢ.liquidus, Ψᵢ.S)
218+
Tᵢ = convert_to_kelvin(ℙᵢ.temperature_units, Tᵢ)
219219
Tₛ⁻ = Ψₛ.T
220220

221221
#=
@@ -227,10 +227,6 @@ end
227227

228228
T★ = Tᵢ - Qₐ * h / k
229229

230-
# Under heating fluxes, cap surface temperature by melting temperature
231-
Tₘ = ℙᵢ.liquidus.freshwater_melting_temperature
232-
Tₘ = convert_to_kelvin(ℙᵢ.temperature_units, Tₘ)
233-
234230
# Fix a NaN
235231
T★ = ifelse(isnan(T★), Tₛ⁻, T★)
236232

@@ -241,6 +237,11 @@ end
241237
abs_ΔT = min(max_ΔT, abs(ΔT★))
242238
Tₛ⁺ = Tₛ⁻ + abs_ΔT * sign(ΔT★)
243239

240+
# Under heating fluxes, cap surface temperature by melting temperature
241+
Tₘ = ℙᵢ.liquidus.freshwater_melting_temperature
242+
Tₘ = convert_to_kelvin(ℙᵢ.temperature_units, Tₘ)
243+
Tₛ⁺ = min(Tₛ⁺, Tₘ)
244+
244245
return Tₛ⁺
245246
end
246247

src/OceanSimulations/barotropic_potential_forcing.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ forcing_barotropic_potential(something) = nothing
2525
forcing_barotropic_potential(f::BarotropicPotentialForcing) = f.potential.data
2626

2727
function forcing_barotropic_potential(mf::MultipleForcings)
28-
n = findfirst(f -> f isa BarotropicPotentialForcing, mf.forcing)
28+
n = findfirst(f -> f isa BarotropicPotentialForcing, mf.forcings)
2929
if isnothing(n)
3030
return nothing
3131
else
32-
return forcing_barotropic_potential(mf.forcing[n])
32+
return forcing_barotropic_potential(mf.forcings[n])
3333
end
3434
end
3535

test/test_ocean_sea_ice_model.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ using CUDA
44
using Oceananigans.OrthogonalSphericalShellGrids
55
using ClimaOcean.OceanSeaIceModels: above_freezing_ocean_temperature!
66
using ClimaSeaIce.SeaIceThermodynamics: melting_temperature
7+
using ClimaSeaIce.SeaIceMomentumEquations
8+
using ClimaSeaIce.Rheologies
79

810
@inline kernel_melting_temperature(i, j, k, grid, liquidus, S) = @inbounds melting_temperature(liquidus, S[i, j, k])
911

@@ -66,10 +68,17 @@ using ClimaSeaIce.SeaIceThermodynamics: melting_temperature
6668
##### Coupled ocean-sea ice and prescribed atmosphere
6769
#####
6870

69-
sea_ice_grid = TripolarGrid(arch; size=(50, 50, 1), z = (-10, 0))
70-
sea_ice_grid = ImmersedBoundaryGrid(sea_ice_grid, GridFittedBottom(bottom_height))
71+
# Adding a sea ice model to the coupled model
72+
τua = Field{Face, Center, Nothing}(grid)
73+
τva = Field{Center, Face, Nothing}(grid)
7174

72-
sea_ice = sea_ice_simulation(sea_ice_grid)
75+
dynamics = SeaIceMomentumEquation(grid;
76+
coriolis = ocean.model.coriolis,
77+
top_momentum_stress = (u=τua, v=τva),
78+
rheology = ElastoViscoPlasticRheology(),
79+
solver = SplitExplicitSolver(120))
80+
81+
sea_ice = sea_ice_simulation(grid; dynamics, advection=WENO(order=7))
7382
liquidus = sea_ice.model.ice_thermodynamics.phase_transitions.liquidus
7483

7584
# Set the ocean temperature and salinity

0 commit comments

Comments
 (0)