Skip to content

Sea ice models

The following describes the currently implemented sea ice models, which are

julia
using SpeedyWeather
subtypes(SpeedyWeather.AbstractSeaIce)
1-element Vector{Any}:
 ThermodynamicSeaIce

No sea ice

You can set sea_ice = nothing which will not touch the initial prognostic_variables.sea_ice_concentration (which when allocated is zero), nor advance it. But you may use set!(simulation, sea_ice_concentration=...) to set the sea ice concentration manually. No sea ice does not do anything on every time step so your manual modifications will prevail after initialize!.

To be used like

julia
spectral_grid = SpectralGrid(trunc=31)
model = PrimitiveWetModel(spectral_grid; sea_ice=nothing)
model.sea_ice

Note that in SpeedyWeather the sea ice model and its albedo are defined independently, means you can have a sea ice model without affecting the albedo and sea_ice=nothing but set the sea ice concentration manually and use its albedo effect, this will be discussed in ThermodynamicSeaIce below.

Thermodynamic sea ice model

Thermodynamic sea ice models do not account for advection through wind and currents or rheological processes but are only concerned with local freezing, ice growth and melt and the thermodynamic processes involved. The ThermodynamicSeaIce model defined here uses only sea ice concentration in units of as a prognostic variable.

Melting and freezing is dependent on the sea surface temperature at the previous time step   and the current and air-sea fluxes applied to get from one time step to the other. Sea ice may modify the sea surface temperatures SST (particularly in the case of freezing) and so we denote the uncorrected SST with meaning that the sea ice time step has not been applied yet. The time step size is .

Air-sea fluxes of heat and humidity are reduced following a simple sea ice concentration-dependent scaling

With   meaning that at a sea ice concentration of   at the previous time step only 1% of the flux goes through the ice. The albedo is chosen linearly with respect to sea ice concentration

with   the albedo of ocean, and   the albedo of ice.

Now determine a tendency in sea ice concentration from the melting and freezing, both proportional to the difference of the sea surface temperature to freezing temperature with freeze rate in and melt rate in . The freeze rate misses a in the units as it is applied with below because   estimates from above not purely the (insulated) flux

And we bound the uncorrected sea surface temperature by freezing at    and the uncorrected sea ice concentration in by

Usage

To be created like

julia
sea_ice = ThermodynamicSeaIce(spectral_grid)
ThermodynamicSeaIce{Float32} <: SpeedyWeather.AbstractSeaIce
├ temp_freeze::Float32 = 271.35
├ melt_rate::Float32 = 1.0e-6
└ freeze_rate::Float32 = 0.1

and most often together with an albedo that scales linearly with sea ice concentration

julia
albedo = OceanLandAlbedo(ocean=OceanSeaIceAlbedo(spectral_grid), land=AlbedoClimatology(spectral_grid))
OceanLandAlbedo <: SpeedyWeather.AbstractAlbedo
├ ocean: OceanSeaIceAlbedo{Float32}
└ land: AlbedoClimatology{Field{Float32, 1, Vector{Float32}, OctahedralGaussianGrid{CPU{KernelAbstractions.CPU}, Vector{UnitRange{Int64}}, Vector{Int64}}}}

Using ocean=GlobalConstantAlbedo(0.06) instead would disable the effect of sea ice on albedo (basically an ocean-coloured sea ice), then passed on to the model constructor

julia
model = PrimitiveWetModel(spectral_grid; sea_ice, albedo)

Note that the insulating factor ( above) of sea ice on air-sea fluxes is controlled in SlabOcean which takes as keyword argument sea_ice_insulation = (x) -> x a function of one argument (the sea ice concentration) yielding the reduction of air-sea fluxes, see Slab ocean. So you likely want to map 0 to 0 with that function to have no insulation (i.e. no impact) in the case of no ice.

Output

And output is added like

julia
add!(model, SpeedyWeather.SeaIceConcentrationOutput())
NetCDFOutput{Field{Float32, 1, Vector{Float32}, FullGaussianGrid{CPU{KernelAbstractions.CPU}, Vector{UnitRange{Int64}}, Vector{Int64}}}}
├ status: inactive/uninitialized
├ write restart file: true (if active)
├ interpolator: AnvilInterpolator{Float32, GridGeometry{OctahedralGaussianGrid{CPU{KernelAbstractions.CPU}, Vector{UnitRange{Int64}}, Vector{Int64}}, Vector{Float32}, Vector{Int64}, Vector{UnitRange{Int64}}}, AnvilLocator{Vector{Float32}, Vector{Int64}}}
├ path: output.nc (overwrite=false)
├ frequency: 21600 seconds
└┐ variables:
 ├ v: meridional wind [m/s]
 ├ humid: specific humidity [kg/kg]
 ├ sic: sea ice concentration [m^2/m^2]
 ├ temp: temperature [degC]
 ├ u: zonal wind [m/s]
 ├ mslp: mean sea-level pressure [hPa]
 └ vor: relative vorticity [s^-1]

or as part of SpeedyWeather.OceanOutput()

julia
add!(model, SpeedyWeather.OceanOutput())
NetCDFOutput{Field{Float32, 1, Vector{Float32}, FullGaussianGrid{CPU{KernelAbstractions.CPU}, Vector{UnitRange{Int64}}, Vector{Int64}}}}
├ status: inactive/uninitialized
├ write restart file: true (if active)
├ interpolator: AnvilInterpolator{Float32, GridGeometry{OctahedralGaussianGrid{CPU{KernelAbstractions.CPU}, Vector{UnitRange{Int64}}, Vector{Int64}}, Vector{Float32}, Vector{Int64}, Vector{UnitRange{Int64}}}, AnvilLocator{Vector{Float32}, Vector{Int64}}}
├ path: output.nc (overwrite=false)
├ frequency: 21600 seconds
└┐ variables:
 ├ v: meridional wind [m/s]
 ├ humid: specific humidity [kg/kg]
 ├ sst: sea surface temperature [degC]
 ├ sic: sea ice concentration [m^2/m^2]
 ├ temp: temperature [degC]
 ├ u: zonal wind [m/s]
 ├ mslp: mean sea-level pressure [hPa]
 └ vor: relative vorticity [s^-1]