-
Notifications
You must be signed in to change notification settings - Fork 28
OMIP prototype #456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
OMIP prototype #456
Changes from 246 commits
4a49b40
fea1854
4441567
7c4aa61
24f7d93
d231995
ca1980c
f448eeb
fed209b
aeedd2f
f954c69
ddee7f0
daeb12f
629d582
54165a0
35fe01d
5548a99
dfb8590
a049dc1
d1e6faf
7186256
a6d758d
0b8624e
f18a772
6679bbd
50a7226
7975dd4
77e440b
5e3c729
b05fb83
501b3fa
f258e29
5751899
af67adc
d008026
83f97e9
03e7f19
1e02dd9
1eedc44
202212c
efa566c
0c8d8b1
0f04d0f
e28b9a4
0e1d4ca
2eeed4c
b27ac12
4d09283
1507936
702fe64
9664584
8392922
d28b611
4b763ee
c306b0f
83331f8
4857647
668bc53
dcce9e2
d5288c1
1322148
2490da2
c411c71
f762205
759c1ac
01e9f05
e48a2b5
0765874
808e6c9
88bd4e8
7cacb1d
7cb8d6b
469883a
86d0bce
509d6b4
308c9e3
06d895c
6397010
ea59ebb
352a3ef
2beac0e
ea86989
89af369
9e2482b
9affa64
7717533
6e0be09
4488c2e
26fde07
a436bed
5746652
5127f05
1037980
71c82f5
bc33d07
ed0d210
5b5b747
28d3e4e
00a2933
d7ef440
b0d1fd3
860ff09
5637600
b3ab48b
d1c7450
a1ede1f
4015bf4
970ffeb
4b4f64e
e6ff0d4
ef45d0c
d96c32b
ea3ee12
9165bd2
add5526
35e2df6
92fda28
ec70ca0
469bcb1
736ac4c
6db860a
5e0997c
049dacd
cf22586
17a2250
d024542
7d6ce58
5e66a54
9063e3e
4fb3526
e7845a5
fca5484
09d22a3
3885668
8bbc3b8
988ec77
3419022
b1430e2
abced34
cf2e735
d0b3bf9
5f3452d
f9613d8
557ddc9
3861dba
d126260
22d6f31
743fa84
f3b1b97
c21aab6
01af82e
91fae63
2bf3999
21e3c57
19ee5e4
e661608
3712296
4ba70a3
6e19316
bb6ee96
4c2570c
ae2602b
4ce942b
b253fef
00205b6
f14ef99
3b6b1ea
78d78c2
ba02445
90843e3
4427feb
6f877ba
f090a62
3c1b9f0
c8d850b
f07686b
9cadad8
29ce3e2
c90cfad
cc6d8e4
cf13948
298bd34
3b5a07d
d8431d1
aba62a5
3bf4880
1683a9c
df335b1
ce29c15
67ac496
4bd2268
084b006
e4bf5fc
87562a5
073d94d
2cc6e4e
da73eb0
a56854d
aabed1b
794da75
421bdc5
e599654
df9303a
e01490a
2d3c595
4896407
bd999f8
511251c
d73900b
bcb80b6
790fff4
b17edf5
7b78ddf
7fc7e18
ee821a1
9136548
caf0e5e
83b886a
cfedf3c
e4c3ba4
829bdb6
8dc252b
55f40e6
60a21ee
3db817a
796c3e6
4ceb7c8
e972fd0
dddafca
fa13e09
c5c4c2f
64881ed
1894d94
e91fbd9
ddd8ba9
29999bd
e13e8aa
90b7322
7704645
9b49800
b5ac778
b06b7a2
9564e2a
6d24bf2
1ee0a89
811128c
4c3f3b3
59e30b8
1778853
94fc935
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| using ClimaOcean | ||
| using ClimaOcean.JRA55 | ||
| using ClimaOcean.DataWrangling: download_dataset | ||
|
|
||
| atmosphere = JRA55PrescribedAtmosphere(; dir="forcing_data/", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trying to encourage people not to set this variable because it makes setups less portable (eg data will be re-downloaded everywhere) |
||
| dataset=JRA55MultipleYears(), | ||
| backend=JRA55NetCDFBackend(10), | ||
| include_rivers_and_icebergs=true) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| using ClimaOcean | ||
| using ClimaSeaIce | ||
| using Oceananigans | ||
| using Oceananigans.Grids | ||
| using Oceananigans.Units | ||
| using Oceananigans.OrthogonalSphericalShellGrids | ||
| using ClimaOcean.OceanSimulations | ||
| using ClimaOcean.ECCO | ||
| using ClimaOcean.JRA55 | ||
| using ClimaOcean.DataWrangling | ||
| using ClimaSeaIce.SeaIceThermodynamics: IceWaterThermalEquilibrium | ||
| using Printf | ||
| using Dates | ||
| using CUDA | ||
|
|
||
| import Oceananigans.OutputWriters: checkpointer_address | ||
|
|
||
| arch = GPU() | ||
|
|
||
| Nx = 360 # longitudinal direction | ||
| Ny = 180 # meridional direction | ||
| Nz = 60 | ||
|
|
||
| z_faces = ExponentialCoordinate(Nz, -6000, 0) | ||
| # z_faces = MutableVerticalDiscretization(z_faces) | ||
|
|
||
| const z_surf = z_faces(Nz) | ||
|
|
||
| grid = TripolarGrid(arch; | ||
| size = (Nx, Ny, Nz), | ||
| z = z_faces, | ||
| halo = (7, 7, 7)) | ||
|
|
||
| bottom_height = regrid_bathymetry(grid; minimum_depth=15, major_basins=1, interpolation_passes=75) | ||
| grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height); active_cells_map=true) | ||
|
|
||
| ##### | ||
| ##### A Propgnostic Ocean model | ||
| ##### | ||
|
|
||
| using Oceananigans.TurbulenceClosures: ExplicitTimeDiscretization | ||
| using Oceananigans.TurbulenceClosures.TKEBasedVerticalDiffusivities: CATKEVerticalDiffusivity, CATKEMixingLength, CATKEEquation | ||
|
|
||
| momentum_advection = WENOVectorInvariant(order=5) | ||
| tracer_advection = WENO(order=5) | ||
|
|
||
| free_surface = SplitExplicitFreeSurface(grid; cfl=0.7, fixed_Δt=45minutes) | ||
|
|
||
| eddy_closure = Oceananigans.TurbulenceClosures.IsopycnalSkewSymmetricDiffusivity(κ_skew=1e3, κ_symmetric=1e3) | ||
| catke_closure = ClimaOcean.OceanSimulations.default_ocean_closure() | ||
| closure = (catke_closure, VerticalScalarDiffusivity(κ=1e-5, ν=1e-4), eddy_closure) | ||
|
|
||
| dataset = EN4Monthly() | ||
| date = DateTime(1958, 1, 1) | ||
| @inline mask(x, y, z, t) = z ≥ z_surf - 1 | ||
| Smetadata = Metadata(:salinity; dataset) | ||
|
|
||
| FS = DatasetRestoring(Smetadata, grid; rate = 1/18days, mask, time_indices_in_memory = 10) | ||
|
|
||
| ocean = ocean_simulation(grid; Δt=1minutes, | ||
| momentum_advection, | ||
| tracer_advection, | ||
| timestepper = :SplitRungeKutta3, | ||
| free_surface, | ||
| forcing = (; S = FS), | ||
| closure) | ||
|
|
||
| dataset = EN4Monthly() | ||
| date = DateTime(1958, 1, 1) | ||
|
|
||
| set!(ocean.model, T=Metadatum(:temperature; dataset, date), | ||
| S=Metadatum(:salinity; dataset, date)) | ||
|
|
||
| @info ocean.model.clock | ||
|
|
||
| ##### | ||
| ##### A Prognostic Sea-ice model | ||
| ##### | ||
|
|
||
| # Default sea-ice dynamics and salinity coupling are included in the defaults | ||
| sea_ice = sea_ice_simulation(grid, ocean; advection=WENO(order=7)) | ||
|
|
||
| set!(sea_ice.model, h=Metadatum(:sea_ice_thickness; dataset=ECCO4Monthly()), | ||
| ℵ=Metadatum(:sea_ice_concentration; dataset=ECCO4Monthly())) | ||
|
|
||
| ##### | ||
| ##### A Prescribed Atmosphere model | ||
| ##### | ||
|
|
||
| dir = "./forcing_data" | ||
| dataset = MultiYearJRA55() | ||
| backend = JRA55NetCDFBackend(100) | ||
|
|
||
| atmosphere = JRA55PrescribedAtmosphere(arch; dir, dataset, backend, include_rivers_and_icebergs=true) | ||
| radiation = Radiation() | ||
|
|
||
| ##### | ||
| ##### An ocean-sea ice coupled model | ||
| ##### | ||
|
|
||
| omip = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation) | ||
| omip = Simulation(omip, Δt=20minutes, stop_time=60days) | ||
|
|
||
| # Figure out the outputs.... | ||
| checkpointer_address(::SeaIceModel) = "SeaIceModel" | ||
|
|
||
| ocean.output_writers[:checkpointer] = Checkpointer(ocean.model, | ||
| schedule = IterationInterval(1000), | ||
| prefix = "ocean_checkpoint_onedegree", | ||
| overwrite_existing = true) | ||
|
|
||
| sea_ice.output_writers[:checkpointer] = Checkpointer(sea_ice.model, | ||
| schedule = IterationInterval(1000), | ||
| prefix = "sea_ice_checkpoint_onedegree", | ||
| overwrite_existing = true) | ||
|
|
||
| wall_time = Ref(time_ns()) | ||
|
|
||
| using Statistics | ||
|
|
||
| function progress(sim) | ||
| sea_ice = sim.model.sea_ice | ||
| ocean = sim.model.ocean | ||
| hmax = maximum(sea_ice.model.ice_thickness) | ||
| ℵmax = maximum(sea_ice.model.ice_concentration) | ||
| Tmax = maximum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature) | ||
| Tmin = minimum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature) | ||
| umax = maximum(ocean.model.velocities.u) | ||
| vmax = maximum(ocean.model.velocities.v) | ||
| wmax = maximum(ocean.model.velocities.w) | ||
|
|
||
| step_time = 1e-9 * (time_ns() - wall_time[]) | ||
|
|
||
| msg1 = @sprintf("time: %s, iteration: %d, Δt: %s, ", prettytime(sim), iteration(sim), prettytime(sim.Δt)) | ||
| msg2 = @sprintf("max(h): %.2e m, max(ℵ): %.2e ", hmax, ℵmax) | ||
| msg4 = @sprintf("extrema(T): (%.2f, %.2f) ᵒC, ", Tmax, Tmin) | ||
| msg5 = @sprintf("maximum(u): (%.2f, %.2f, %.2f) m/s, ", umax, vmax, wmax) | ||
| msg6 = @sprintf("wall time: %s \n", prettytime(step_time)) | ||
|
|
||
| @info msg1 * msg2 * msg4 * msg5 * msg6 | ||
|
|
||
| wall_time[] = time_ns() | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| # And add it as a callback to the simulation. | ||
| add_callback!(omip, progress, IterationInterval(1)) | ||
|
|
||
| run!(omip) | ||
|
|
||
| omip.Δt = 30minutes | ||
| omip.stop_time = 58 * 365days | ||
|
|
||
| run!(omip) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| using ClimaOcean | ||
| using ClimaSeaIce | ||
| using Oceananigans | ||
| using Oceananigans.Grids | ||
| using Oceananigans.Units | ||
| using Oceananigans.OrthogonalSphericalShellGrids | ||
| using ClimaOcean.OceanSimulations | ||
| using ClimaOcean.ECCO | ||
| using ClimaOcean.JRA55 | ||
| using ClimaOcean.DataWrangling | ||
| using ClimaSeaIce.SeaIceThermodynamics: IceWaterThermalEquilibrium | ||
| using Printf | ||
| using Dates | ||
| using CUDA | ||
|
|
||
| import Oceananigans.OutputWriters: checkpointer_address | ||
|
|
||
| function synch!(clock1::Clock, clock2) | ||
| # Synchronize the clocks | ||
| clock1.time = clock2.time | ||
| clock1.iteration = clock2.iteration | ||
| clock1.last_Δt = clock2.last_Δt | ||
| end | ||
|
|
||
| synch!(model1, model2) = synch!(model1.clock, model2.clock) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you need this please put it in a separate PR and get that merged, because people want to use stuff |
||
|
|
||
| arch = GPU() | ||
|
|
||
| Nx = 2160 # longitudinal direction | ||
| Ny = 1080 # meridional direction | ||
| Nz = 60 | ||
|
|
||
| r_faces = ClimaOcean.ExponentialCoordinate(Nz, -6000) | ||
| z_faces = MutableVerticalDiscretization(r_faces) | ||
|
|
||
| grid = TripolarGrid(arch; | ||
| size = (Nx, Ny, Nz), | ||
| z = z_faces, | ||
| halo = (7, 7, 7)) | ||
|
|
||
| bottom_height = regrid_bathymetry(grid; minimum_depth=15, major_basins=1, interpolation_passes=15) | ||
| grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height); active_cells_map=true) | ||
|
|
||
| ##### | ||
| ##### A Propgnostic Ocean model | ||
| ##### | ||
|
|
||
| using Oceananigans.TurbulenceClosures: ExplicitTimeDiscretization | ||
| using Oceananigans.TurbulenceClosures.TKEBasedVerticalDiffusivities: CATKEVerticalDiffusivity, CATKEMixingLength, CATKEEquation | ||
|
|
||
| momentum_advection = WENOVectorInvariant() | ||
| tracer_advection = WENO(order=7) | ||
|
|
||
| free_surface = SplitExplicitFreeSurface(grid; cfl=0.7, fixed_Δt=10minutes) | ||
|
|
||
| mixing_length = CATKEMixingLength(Cᵇ=0.01) | ||
| turbulent_kinetic_energy_equation = CATKEEquation(Cᵂϵ=1.0) | ||
|
|
||
| catke_closure = CATKEVerticalDiffusivity(; mixing_length, turbulent_kinetic_energy_equation) | ||
| closure = (catke_closure, VerticalScalarDiffusivity(κ=1e-5, ν=1e-5)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @simone-silvestri, why change CATKE defaults?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also it's wrong to add an additional background diffusivity. CATKE already introduces a background diffusivity via the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Otherwise I guess it's ok to experiment with different parameter choices, if there are choices that work better we can make them default in Oceananigans. |
||
|
|
||
| ocean = ocean_simulation(grid; Δt=1minutes, | ||
| momentum_advection, | ||
| tracer_advection, | ||
| free_surface, | ||
| closure) | ||
|
|
||
| dataset = ECCO4Monthly() | ||
|
|
||
| set!(ocean.model, T=Metadatum(:temperature; dataset), | ||
| S=Metadatum(:salinity; dataset)) | ||
|
|
||
| ##### | ||
| ##### A Prognostic Sea-ice model | ||
| ##### | ||
|
|
||
| # Default sea-ice dynamics and salinity coupling are included in the defaults | ||
| sea_ice = sea_ice_simulation(grid; advection=WENO(order=7)) | ||
|
|
||
| set!(sea_ice.model, h=Metadatum(:sea_ice_thickness; dataset), | ||
| ℵ=Metadatum(:sea_ice_concentration; dataset)) | ||
|
|
||
| ##### | ||
| ##### A Prescribed Atmosphere model | ||
| ##### | ||
|
|
||
| dir = "./forcing_data" | ||
| dataset = MultiYearJRA55() | ||
| backend = JRA55NetCDFBackend(100) | ||
|
|
||
| atmosphere = JRA55PrescribedAtmosphere(arch; dir, dataset, backend, include_rivers_and_icebergs=true) | ||
| radiation = Radiation() | ||
|
|
||
| ##### | ||
| ##### An ocean-sea ice coupled model | ||
| ##### | ||
|
|
||
| omip = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation) | ||
| omip = Simulation(omip, Δt=20, stop_time=60days) | ||
|
|
||
| # Figure out the outputs.... | ||
|
|
||
| checkpointer_address(::SeaIceModel) = "SeaIceModel" | ||
|
|
||
| ocean.output_writers[:checkpointer] = Checkpointer(ocean.model, | ||
| schedule = IterationInterval(10000), | ||
| prefix = "ocean_checkpoint", | ||
| overwrite_existing = true) | ||
|
|
||
| sea_ice.output_writers[:checkpointer] = Checkpointer(sea_ice.model, | ||
| schedule = IterationInterval(10000), | ||
| prefix = "sea_ice_checkpoint", | ||
| overwrite_existing = true) | ||
|
|
||
| wall_time = Ref(time_ns()) | ||
|
|
||
| using Statistics | ||
|
|
||
| function progress(sim) | ||
| sea_ice = sim.model.sea_ice | ||
| ocean = sim.model.ocean | ||
| hmax = maximum(sea_ice.model.ice_thickness) | ||
| ℵmax = maximum(sea_ice.model.ice_concentration) | ||
| Tmax = maximum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature) | ||
| Tmin = minimum(sim.model.interfaces.atmosphere_sea_ice_interface.temperature) | ||
| umax = maximum(ocean.model.velocities.u) | ||
| vmax = maximum(ocean.model.velocities.v) | ||
| wmax = maximum(ocean.model.velocities.w) | ||
|
|
||
| step_time = 1e-9 * (time_ns() - wall_time[]) | ||
|
|
||
| msg1 = @sprintf("time: %s, iteration: %d, Δt: %s, ", prettytime(sim), iteration(sim), prettytime(sim.Δt)) | ||
| msg2 = @sprintf("max(h): %.2e m, max(ℵ): %.2e ", hmax, ℵmax) | ||
| msg4 = @sprintf("extrema(T): (%.2f, %.2f) ᵒC, ", Tmax, Tmin) | ||
| msg5 = @sprintf("maximum(u): (%.2f, %.2f, %.2f) m/s, ", umax, vmax, wmax) | ||
| msg6 = @sprintf("wall time: %s \n", prettytime(step_time)) | ||
|
|
||
| @info msg1 * msg2 * msg4 * msg5 * msg6 | ||
|
|
||
| wall_time[] = time_ns() | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| # And add it as a callback to the simulation. | ||
| add_callback!(omip, progress, IterationInterval(50)) | ||
|
|
||
| run!(omip) | ||
|
|
||
| omip.Δt = 6minutes | ||
| omip.stop_time = 58 * 365days | ||
|
|
||
| run!(omip) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't need these right?