Skip to content

Commit 409486c

Browse files
An arctic simulation to test the coupling between sea ice and ocean (#369)
* Update Bathymetry.jl * add a fill halo * starting * some changes * start changing stuff * arctic simulation * works * let's go * continue * a default inpainting for ECCO * try it out * run it on the GPU * churning on * try it out like this * remove this constant coefficient fluxes * add fluxes * a very diffusive ocean * just push it with the diffusivity * unfortunately it crashes about 5 minutes * try with 8mins * to change evenutally * 5 minutes * remove the thermodynamic time step * better comments * update to new ClimaSeaIce * change * update to new syntax * update to new syntax * reference heat capactity * remove prescribed ocean * vestigial code
1 parent fa88a47 commit 409486c

File tree

3 files changed

+178
-2
lines changed

3 files changed

+178
-2
lines changed

experiments/arctic_simulation.jl

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
using ClimaOcean
2+
using ClimaSeaIce
3+
using Oceananigans
4+
using Oceananigans.Grids
5+
using Oceananigans.Units
6+
using Oceananigans.OrthogonalSphericalShellGrids
7+
using ClimaOcean.OceanSimulations
8+
using ClimaOcean.ECCO
9+
using ClimaOcean.ECCO: all_ECCO_dates
10+
using ClimaSeaIce.SeaIceThermodynamics: IceWaterThermalEquilibrium
11+
using Printf
12+
13+
using CUDA
14+
CUDA.device!(1)
15+
16+
r_faces = ClimaOcean.exponential_z_faces(; Nz=30, h=10, depth=2000)
17+
z_faces = MutableVerticalDiscretization(r_faces)
18+
19+
Nx = 180 # longitudinal direction -> 250 points is about 1.5ᵒ resolution
20+
Ny = 180 # meridional direction -> same thing, 48 points is about 1.5ᵒ resolution
21+
Nz = length(r_faces) - 1
22+
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))
30+
31+
bottom_height = regrid_bathymetry(grid; minimum_depth=15, major_basins=1)
32+
33+
grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height))
34+
35+
#####
36+
##### A Propgnostic Ocean model
37+
#####
38+
39+
# A very diffusive ocean
40+
momentum_advection = WENOVectorInvariant(order=3)
41+
tracer_advection = WENO(order=3)
42+
43+
free_surface = SplitExplicitFreeSurface(grid; cfl=0.7)
44+
closure = ClimaOcean.OceanSimulations.default_ocean_closure()
45+
46+
ocean = ocean_simulation(grid;
47+
momentum_advection,
48+
tracer_advection,
49+
free_surface,
50+
closure)
51+
52+
set!(ocean.model, T=ECCOMetadata(:temperature),
53+
S=ECCOMetadata(:salinity))
54+
55+
#####
56+
##### A Prognostic Sea-ice model
57+
#####
58+
59+
# Remember to pass the SSS as a bottom bc to the sea ice!
60+
SSS = view(ocean.model.tracers.S, :, :, grid.Nz)
61+
bottom_heat_boundary_condition = IceWaterThermalEquilibrium(SSS)
62+
63+
sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition, dynamics=nothing, advection=nothing)
64+
65+
set!(sea_ice.model, h=ECCOMetadata(:sea_ice_thickness),
66+
=ECCOMetadata(:sea_ice_concentration))
67+
68+
#####
69+
##### A Prescribed Atmosphere model
70+
#####
71+
72+
atmosphere = JRA55PrescribedAtmosphere(GPU(); backend=JRA55NetCDFBackend(40))
73+
radiation = Radiation()
74+
75+
#####
76+
##### Arctic coupled model
77+
#####
78+
79+
arctic = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation)
80+
arctic = Simulation(arctic, Δt=5minutes, stop_time=365days)
81+
82+
# 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ⁿ.
87+
88+
# Fluxes
89+
Tu = arctic.model.interfaces.atmosphere_sea_ice_interface.temperature
90+
= arctic.model.interfaces.atmosphere_sea_ice_interface.fluxes.latent_heat
91+
= arctic.model.interfaces.atmosphere_sea_ice_interface.fluxes.sensible_heat
92+
Qⁱ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.interface_heat
93+
Qᶠ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.frazil_heat
94+
Qᵗ = arctic.model.interfaces.net_fluxes.sea_ice_top.heat
95+
Qᴮ = arctic.model.interfaces.net_fluxes.sea_ice_bottom.heat
96+
97+
# Output writers
98+
arctic.output_writers[:vars] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Gh, Gℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ),
99+
filename = "sea_ice_quantities.jld2",
100+
schedule = IterationInterval(12),
101+
overwrite_existing=true)
102+
103+
arctic.output_writers[:avrages] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ),
104+
filename = "averaged_sea_ice_quantities.jld2",
105+
schedule = AveragedTimeInterval(1days),
106+
overwrite_existing=true)
107+
108+
wall_time = Ref(time_ns())
109+
110+
using Statistics
111+
112+
function progress(sim)
113+
sea_ice = sim.model.sea_ice
114+
hmax = maximum(sea_ice.model.ice_thickness)
115+
ℵmax = maximum(sea_ice.model.ice_concentration)
116+
hmean = mean(sea_ice.model.ice_thickness)
117+
ℵmean = mean(sea_ice.model.ice_concentration)
118+
Tmax = maximum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature)
119+
Tmin = minimum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature)
120+
121+
step_time = 1e-9 * (time_ns() - wall_time[])
122+
123+
msg1 = @sprintf("time: %s, iteration: %d, Δt: %s, ", prettytime(sim), iteration(sim), prettytime(sim.Δt))
124+
msg2 = @sprintf("max(h): %.2e m, max(ℵ): %.2e ", hmax, ℵmax)
125+
msg3 = @sprintf("mean(h): %.2e m, mean(ℵ): %.2e ", hmean, ℵmean)
126+
msg4 = @sprintf("extrema(T): (%.2f, %.2f) ᵒC, ", Tmax, Tmin)
127+
msg5 = @sprintf("wall time: %s \n", prettytime(step_time))
128+
129+
@info msg1 * msg2 * msg3 * msg4 * msg5
130+
131+
wall_time[] = time_ns()
132+
133+
return nothing
134+
end
135+
136+
# And add it as a callback to the simulation.
137+
add_callback!(arctic, progress, IterationInterval(10))
138+
139+
run!(arctic)
140+
141+
#####
142+
##### Comparison to ECCO Climatology
143+
#####
144+
145+
version = ECCO4Monthly()
146+
dates = all_ECCO_dates(version)[1:12]
147+
148+
h_metadata = ECCOMetadata(:sea_ice_thickness; version, dates)
149+
ℵ_metadata = ECCOMetadata(:sea_ice_concentration; version, dates)
150+
151+
# Montly averaged ECCO data
152+
hE = ECCOFieldTimeSeries(h_metadata, grid; time_indices_in_memory=12)
153+
ℵE = ECCOFieldTimeSeries(ℵ_metadata, grid; time_indices_in_memory=12)
154+
155+
# Daily averaged Model output
156+
h = FieldTimeSeries("averaged_sea_ice_quantities.jld2", "h")
157+
= FieldTimeSeries("averaged_sea_ice_quantities.jld2", "")
158+
159+
# Montly average the model output
160+
hm = FieldTimeSeries{Center, Center, Nothing}(grid, hE.times; backend=InMemory())
161+
ℵm = FieldTimeSeries{Center, Center, Nothing}(grid, hE.times; backend=InMemory())
162+
163+
for (i, time) in enumerate(hm.times)
164+
counter = 0
165+
for (j, t) in enumerate(h.times)
166+
if t time
167+
hm[i] .+= h[j]
168+
ℵm[i] .+= ℵ[j]
169+
counter += 1
170+
end
171+
end
172+
@show counter
173+
hm[i] ./= counter
174+
ℵm[i] ./= counter
175+
end

src/DataWrangling/ECCO/ECCO.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ end
3232

3333
include("ECCO_metadata.jl")
3434
include("ECCO_mask.jl")
35-
include("ECCO_restoring.jl")
3635

3736
# Vertical coordinate
3837
const ECCO_z = [
@@ -273,5 +272,7 @@ function set!(field::Field, ECCO_metadata::ECCOMetadata; kw...)
273272
return field
274273
end
275274

275+
include("ECCO_restoring.jl")
276+
276277
end # Module
277278

src/DataWrangling/ECCO/ECCO_restoring.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ end
147147
function ECCOFieldTimeSeries(metadata::ECCOMetadata, grid::AbstractGrid;
148148
time_indices_in_memory = 2,
149149
time_indexing = Cyclical(),
150-
inpainting = nothing,
150+
inpainting = default_inpainting(metadata),
151151
cache_inpainted_data = true)
152152

153153
# Make sure all the required individual files are downloaded

0 commit comments

Comments
 (0)