Skip to content

Commit c068af0

Browse files
committed
adding ClimaSeaIce
1 parent b5ef5e8 commit c068af0

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import Oceananigans as OC
2+
import ClimaOcean as CO
3+
import ClimaCoupler: Checkpointer, FieldExchanger, FluxCalculator, Interfacer, Utilities
4+
import ClimaComms
5+
import ClimaCore as CC
6+
import Thermodynamics as TD
7+
import ClimaOcean.EN4: download_dataset
8+
using KernelAbstractions: @kernel, @index, @inbounds
9+
10+
"""
11+
ClimaSeaIceSimulation{SIM, A, OPROP, REMAP}
12+
13+
The ClimaCoupler simulation object used to run with Oceananigans.
14+
This type is used by the coupler to indicate that this simulation
15+
is an surface/ocean simulation for dispatch.
16+
17+
It contains the following objects:
18+
- `sea_ice::SIM`: The ClimaSeaIce simulation object.
19+
- `area_fraction::A`: A ClimaCore Field representing the surface area fraction of this component model on the exchange grid.
20+
- `melting_speed::MS`: An constant characteristic speed for melting/freezing.
21+
- `remapping::REMAP`: Objects needed to remap from the exchange (spectral) grid to Oceananigans spaces.
22+
"""
23+
struct ClimaSeaIceSimulation{SIM,A,MS,REMAP} <: Interfacer.SeaIceModelSimulation
24+
sea_ice::SIM
25+
area_fraction::A
26+
melting_speed::MS
27+
remapping::REMAP
28+
end
29+
30+
"""
31+
ClimaSeaIceSimulation()
32+
33+
Creates an OceananigansSimulation object containing a model, an integrator, and
34+
a surface area fraction field.
35+
This type is used to indicate that this simulation is an ocean simulation for
36+
dispatch in coupling.
37+
38+
Specific details about the default model configuration
39+
can be found in the documentation for `ClimaOcean.ocean_simulation`.
40+
"""
41+
function ClimaSeaIceSimulation(area_fraction, ocean; output_dir)
42+
# Initialize the sea ice with the same grid as the ocean
43+
# Initially no sea ice is present
44+
grid = ocean.ocean.model.grid
45+
advection = ocean.ocean.model.advection.T
46+
sea_ice = CO.sea_ice_simulation(grid, ocean.ocean; advection)
47+
48+
melting_speed = 1e-4
49+
remapping = ocean.remapping
50+
51+
# Before version 0.96.22, the NetCDFWriter was broken on GPU
52+
if arch isa OC.CPU || pkgversion(OC) >= v"0.96.22"
53+
# TODO maybe this is broken
54+
# Save all tracers and velocities to a NetCDF file at daily frequency
55+
outputs = prognostic_fields(sea_ice.model)
56+
netcdf_writer = OC.NetCDFWriter(
57+
sea_ice.model,
58+
outputs;
59+
schedule = OC.TimeInterval(86400), # Daily output
60+
filename = joinpath(output_dir, "seaice_diagnostics.nc"),
61+
indices = (:, :, grid.Nz),
62+
overwrite_existing = true,
63+
array_type = Array{Float32},
64+
)
65+
sea_ice.output_writers[:diagnostics] = netcdf_writer
66+
end
67+
68+
sim = ClimaSeaIceSimulation(sea_ice, area_fraction, melting_speed, remapping)
69+
return sim
70+
end

experiments/ClimaEarth/components/ocean/oceananigans.jl

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ function OceananigansSimulation(
8888
active_cells_map = true,
8989
)
9090

91+
# TODO use_restoring only if not using ClimaSeaIce
9192
use_restoring = start_date + Dates.Month(1) < stop_date
9293

9394
if use_restoring
@@ -108,7 +109,21 @@ function OceananigansSimulation(
108109
end
109110

110111
# Create ocean simulation
111-
ocean = CO.ocean_simulation(grid; forcing)
112+
free_surface = SplitExplicitFreeSurface(grid; substeps = 70)
113+
momentum_advection = WENOVectorInvariant(order = 5)
114+
tracer_advection = WENO(order = 5)
115+
eddy_closure = Oceananigans.TurbulenceClosures.IsopycnalSkewSymmetricDiffusivity(κ_skew = 2e3, κ_symmetric = 2e3)
116+
vertical_mixing = ClimaOcean.OceanSimulations.default_ocean_closure()
117+
horizontal_viscosity = HorizontalScalarDiffusivity= 4000)
118+
119+
ocean = CO.ocean_simulation(
120+
grid;
121+
forcing,
122+
momentum_advection,
123+
tracer_advection,
124+
free_surface,
125+
closure = (eddy_closure, horizontal_viscosity, vertical_mixing),
126+
)
112127

113128
# Set initial condition to EN4 state estimate at start_date
114129
OC.set!(ocean.model, T = en4_temperature[1], S = en4_salinity[1])
@@ -147,8 +162,6 @@ function OceananigansSimulation(
147162

148163
# Before version 0.96.22, the NetCDFWriter was broken on GPU
149164
if arch isa OC.CPU || pkgversion(OC) >= v"0.96.22"
150-
# TODO: Add more diagnostics, make them dependent on simulation duration, take
151-
# monthly averages
152165
# Save all tracers and velocities to a NetCDF file at daily frequency
153166
outputs = merge(ocean.model.tracers, ocean.model.velocities)
154167
netcdf_writer = OC.NetCDFWriter(
@@ -253,10 +266,8 @@ Interfacer.get_field(sim::OceananigansSimulation, ::Val{:roughness_momentum}) =
253266
Float32(5.8e-5)
254267
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:beta}) = Float32(1)
255268
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:emissivity}) = Float32(0.97)
256-
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:surface_direct_albedo}) =
257-
Float32(0.06)
258-
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:surface_diffuse_albedo}) =
259-
Float32(0.06)
269+
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:surface_direct_albedo}) = Float32(0.011)
270+
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:surface_diffuse_albedo}) = Float32(0.069)
260271

261272
# NOTE: This is 3D, but it will be remapped to 2D
262273
Interfacer.get_field(sim::OceananigansSimulation, ::Val{:surface_temperature}) =

0 commit comments

Comments
 (0)