-
Couldn't load subscription status.
- Fork 22
Add SpeedyWeather extension #463
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
Open
glwagner
wants to merge
68
commits into
main
Choose a base branch
from
speedy-ext
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
54548ab
Add SpeedyWeather extension
glwagner 36a6bdf
add a few things
glwagner 6b19679
start populating the model
simone-silvestri e3fc3e8
change project
simone-silvestri 8fc92aa
add speedy
glwagner 22cfaba
Merge branch 'speedy-ext' of https://github.com/CliMA/ClimaOcean.jl i…
glwagner b702959
building
glwagner 007aed0
grid test
glwagner a3aa03f
better comment
simone-silvestri 9e5e4af
this should start working?
simone-silvestri 93d054d
comments
simone-silvestri 60c6476
import stuff
simone-silvestri 3d313d7
some improvements
simone-silvestri c663312
add the regridding
simone-silvestri e33b6af
this should wortk
simone-silvestri c83fa03
do not use regrid!
simone-silvestri 292c3c8
remove the regrid!
simone-silvestri a81ab5f
this works?
simone-silvestri 24c88fa
going
simone-silvestri 2152712
this seems to work
simone-silvestri 269ca76
still some NaNs to fix
simone-silvestri 876b3a7
suggested changes
simone-silvestri 8526e35
Merge branch 'main' into speedy-ext
simone-silvestri 148d9c3
Merge branch 'main' into speedy-ext
simone-silvestri 2dc2b86
starting stuff
simone-silvestri 4148fd7
simulation is running!
simone-silvestri 122e27b
now everything works
simone-silvestri c7b2949
use functions
simone-silvestri 8c23280
speed up stuff
simone-silvestri 90ea8bc
coupled simulation that runs
simone-silvestri 5872737
using trunc=63
simone-silvestri e433d9e
small fix
simone-silvestri 3ad33d7
add the sst
simone-silvestri 0fb3f26
no arch
simone-silvestri 5832320
more changes
simone-silvestri 34d54f3
make sure it is kelvin
simone-silvestri 5e05425
coupled
simone-silvestri acb4be4
Merge branch 'main' into speedy-ext
simone-silvestri 7524c1d
add this to tests
simone-silvestri f1ebfcc
Merge branch 'speedy-ext' of github.com:CliMA/ClimaOcean.jl into spee…
simone-silvestri 3b1a977
test this out
simone-silvestri e68d16b
add this
simone-silvestri 99cefaa
try high res
simone-silvestri dacc8fc
high res
simone-silvestri 4281c44
add more packages
simone-silvestri 2c38620
thos now should work
simone-silvestri f83c78c
Merge branch 'speedy-ext' of github.com:CliMA/ClimaOcean.jl into spee…
simone-silvestri 0eaac46
we do not need PyCall
simone-silvestri e819c1b
make it work with PythonCall
simone-silvestri c04115f
probably better like this?
simone-silvestri dd41c84
this should work now
simone-silvestri c52000d
molmass ratio
simone-silvestri bbc7bcb
add
simone-silvestri 0db655f
add a coupled simulation
simone-silvestri 6391632
go ahead
simone-silvestri aebdd57
add this
simone-silvestri fd652e1
Merge branch 'main' into speedy-ext
simone-silvestri fb09b37
add it as an example
simone-silvestri 7876e35
Merge branch 'speedy-ext' of github.com:CliMA/ClimaOcean.jl into spee…
simone-silvestri a469d8c
Merge branch 'main' into speedy-ext
simone-silvestri 5452faf
bugfix
simone-silvestri 7223d4d
Merge branch 'speedy-ext' of github.com:CliMA/ClimaOcean.jl into spee…
simone-silvestri a153dd9
Update examples/coupled_simulation.jl
simone-silvestri 3ba6b53
Update examples/coupled_simulation.jl
simone-silvestri ba68985
Update docs/make.jl
simone-silvestri 255f44c
corrections
simone-silvestri 6aef9ba
new versions
simone-silvestri 7f17322
Merge branch 'speedy-ext' of github.com:CliMA/ClimaOcean.jl into spee…
simone-silvestri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,2 @@ | ||
|
|
||
| [pip.deps] | ||
| copernicusmarine = ">=2.0.0" | ||
| xarray = ">=2024.7.0" | ||
| numpy = ">=2.0.0" | ||
| jax = ">=0.6" | ||
| tensorflow = ">=2.17" | ||
| [deps] | ||
| xesmf = "0.8.10" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| # # Global coupled atmosphere and ocean--sea ice simulation | ||
| # | ||
| # This example configures a global ocean--sea ice simulation at 1ᵒ horizontal resolution with | ||
| # realistic bathymetry and a few closures including the "Gent-McWilliams" `IsopycnalSkewSymmetricDiffusivity`. | ||
| # The atmosphere is represented by a SpeecdyWeather model at T63 resolution (approximately 1.875ᵒ). | ||
| # and initialized by temperature, salinity, sea ice concentration, and sea ice thickness | ||
| # from the ECCO state estimate. | ||
| # | ||
| # For this example, we need Oceananigans.HydrostaticFreeSurfaceModel (the ocean), ClimaSeaIce.SeaIceModel (the sea ice) and | ||
| # SpeedyWeather.PrimitiveWetModel (the atmosphere), coupled and orchestrated by ClimaOcean.OceanSeaIceModel (the coupled system). | ||
|
|
||
| using Oceananigans, ClimaSeaIce, SpeedyWeather, ClimaOcean | ||
| using NCDatasets, CairoMakie | ||
| using Oceananigans.Units | ||
| using Printf, Statistics, Dates | ||
|
|
||
| # ## Ocean and sea-ice model configuration | ||
| # The ocean and sea-ice are configured in accordance with the "one_degree_simulation" example | ||
| # https://clima.github.io/ClimaOceanDocumentation/dev/literated/one_degree_simulation/ | ||
| # The first step is to create the grid with realistic bathymetry. | ||
|
|
||
| Nx = 360 | ||
| Ny = 180 | ||
| Nz = 30 | ||
|
|
||
| r_faces = ExponentialCoordinate(Nz, -4000, 0) | ||
| grid = TripolarGrid(CPU(); size=(Nx, Ny, Nz), z=r_faces, halo=(6, 6, 5)) | ||
|
|
||
| # Regridding the bathymetry... | ||
|
|
||
| bottom_height = regrid_bathymetry(grid; major_basins=1, interpolation_passes=15) | ||
| grid = ImmersedBoundaryGrid(grid, GridFittedBottom(bottom_height); active_cells_map=true) | ||
|
|
||
| # Now we can specify the numerical details and closures for the ocean simulation. | ||
|
|
||
| momentum_advection = WENOVectorInvariant(order=5) | ||
| tracer_advection = WENO(order=5) | ||
| free_surface = SplitExplicitFreeSurface(grid; substeps=80) | ||
|
|
||
| catke_closure = ClimaOcean.OceanSimulations.default_ocean_closure() | ||
| eddy_closure = Oceananigans.TurbulenceClosures.IsopycnalSkewSymmetricDiffusivity(κ_skew=1e3, κ_symmetric=1e3) | ||
| closures = (catke_closure, eddy_closure, VerticalScalarDiffusivity(κ=1e-5, ν=1e-4)) | ||
|
|
||
| # The ocean simulation, complete with initial conditions for temperature and salinity from ECCO. | ||
|
|
||
| ocean = ocean_simulation(grid; | ||
| momentum_advection, | ||
| tracer_advection, | ||
| free_surface, | ||
| timestepper = :SplitRungeKutta3, | ||
| closure = closures) | ||
|
|
||
| Oceananigans.set!(ocean.model, T=Metadatum(:temperature, dataset=ECCO4Monthly()), | ||
| S=Metadatum(:salinity, dataset=ECCO4Monthly())) | ||
|
|
||
|
|
||
| # The sea-ice simulation, complete with initial conditions for sea-ice thickness and concentration from ECCO. | ||
|
|
||
| dynamics = ClimaOcean.SeaIceSimulations.sea_ice_dynamics(grid, ocean; solver=ClimaSeaIce.SeaIceDynamics.SplitExplicitSolver(100)) | ||
| sea_ice = sea_ice_simulation(grid, ocean; dynamics, advection=WENO(order=7)) | ||
|
|
||
| Oceananigans.set!(sea_ice.model, h=Metadatum(:sea_ice_thickness, dataset=ECCO4Monthly()), | ||
| ℵ=Metadatum(:sea_ice_concentration, dataset=ECCO4Monthly())) | ||
|
|
||
| # ## Atmosphere model configuration | ||
| # The atmosphere is provided by SpeedyWeather.jl. Here we configure a T63L8 model with a 3 hour output interval. | ||
| # The `atmosphere_simulation` function takes care of building an atmosphere model with appropriate | ||
| # hooks for ClimaOcean to compute intercomponent fluxes. We also set the output interval to 3 hours. | ||
|
|
||
| spectral_grid = SpectralGrid(trunc=63, nlayers=8, Grid=FullClenshawGrid) | ||
| atmosphere = atmosphere_simulation(spectral_grid; output=true) | ||
| atmosphere.model.output.output_dt = Hour(3) | ||
|
|
||
| # ## The coupled model | ||
| # Now we can build the coupled model. We need to specify the time step for the coupled model. | ||
| # We decide to step the global model every 2 atmosphere time steps. (i.e. the ocean and the | ||
| # sea-ice will be stepped every two atmosphere time steps). | ||
|
|
||
| Δt = 2 * convert(eltype(grid), atmosphere.model.time_stepping.Δt_sec) | ||
|
|
||
| # We build the complete model. Since radiation is idealized in this example, we set the emissivities to zero. | ||
|
|
||
| radiation = Radiation(ocean_emissivity=0.0, sea_ice_emissivity=0.0) | ||
| earth_model = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation) | ||
| earth = Oceananigans.Simulation(earth_model; Δt, stop_time=360days) | ||
|
|
||
| # ## Running the simulation | ||
| # We can now run the simulation. We add a callback to monitor the progress of the simulation | ||
| # and write outputs to disk every 3 hours. | ||
|
|
||
| wall_time = Ref(time_ns()) | ||
|
|
||
| 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) | ||
| uimax = maximum(abs, sea_ice.model.velocities.u) | ||
| vimax = maximum(abs, sea_ice.model.velocities.v) | ||
| uomax = maximum(abs, ocean.model.velocities.u) | ||
| vomax = maximum(abs, ocean.model.velocities.v) | ||
|
|
||
| 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) | ||
| msg3 = @sprintf("max uᵢ: (%.2f, %.2f) m s⁻¹, ", uimax, vimax) | ||
| msg4 = @sprintf("max uₒ: (%.2f, %.2f) m s⁻¹, ", uomax, vomax) | ||
| msg5 = @sprintf("wall time: %s \n", prettytime(step_time)) | ||
|
|
||
| @info msg1 * msg2 * msg3 * msg4 * msg5 | ||
|
|
||
| wall_time[] = time_ns() | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| outputs = merge(ocean.model.velocities, ocean.model.tracers) | ||
| sea_ice_fields = merge(sea_ice.model.velocities, sea_ice.model.dynamics.auxiliaries.fields, | ||
| (; h=sea_ice.model.ice_thickness, ℵ=sea_ice.model.ice_concentration)) | ||
|
|
||
| ocean.output_writers[:free_surf] = JLD2Writer(ocean.model, (; η=ocean.model.free_surface.η); | ||
| overwrite_existing=true, | ||
| schedule=TimeInterval(3600 * 3), | ||
| filename="ocean_free_surface.jld2") | ||
|
|
||
| ocean.output_writers[:surface] = JLD2Writer(ocean.model, outputs; | ||
| overwrite_existing=true, | ||
| schedule=TimeInterval(3600 * 3), | ||
| filename="ocean_surface_fields.jld2", | ||
| indices=(:, :, grid.Nz)) | ||
|
|
||
| sea_ice.output_writers[:fields] = JLD2Writer(sea_ice.model, sea_ice_fields; | ||
| overwrite_existing=true, | ||
| schedule=TimeInterval(3600 * 3), | ||
| filename="sea_ice_fields.jld2") | ||
|
|
||
| Qcao = earth.model.interfaces.atmosphere_ocean_interface.fluxes.sensible_heat | ||
| Qvao = earth.model.interfaces.atmosphere_ocean_interface.fluxes.latent_heat | ||
| τxao = earth.model.interfaces.atmosphere_ocean_interface.fluxes.x_momentum | ||
| τyao = earth.model.interfaces.atmosphere_ocean_interface.fluxes.y_momentum | ||
| Qcai = earth.model.interfaces.atmosphere_sea_ice_interface.fluxes.sensible_heat | ||
| Qvai = earth.model.interfaces.atmosphere_sea_ice_interface.fluxes.latent_heat | ||
| τxai = earth.model.interfaces.atmosphere_sea_ice_interface.fluxes.x_momentum | ||
| τyai = earth.model.interfaces.atmosphere_sea_ice_interface.fluxes.y_momentum | ||
| Qoi = earth.model.interfaces.net_fluxes.sea_ice_bottom.heat | ||
| Soi = earth.model.interfaces.sea_ice_ocean_interface.fluxes.salt | ||
| fluxes = (; Qcao, Qvao, τxao, τyao, Qcai, Qvai, τxai, τyai, Qoi, Soi) | ||
|
|
||
| earth.output_writers[:fluxes] = JLD2Writer(earth.model.ocean.model, fluxes; | ||
| overwrite_existing=true, | ||
| schedule=TimeInterval(3600 * 3), | ||
| filename="intercomponent_fluxes.jld2") | ||
|
|
||
| add_callback!(earth, progress, IterationInterval(100)) | ||
|
|
||
| Oceananigans.run!(earth) | ||
|
|
||
| # ## Visualizing the results | ||
| # We can visualize some of the results. Here we plot the surface speeds in the atmosphere, ocean, and sea-ice | ||
| # as well as the 2m temperature in the atmosphere, the sea surface temperature, and the sensible and latent heat | ||
| # fluxes at the atmosphere-ocean interface. | ||
|
|
||
| SWO = Dataset("run_0001/output.nc") | ||
|
|
||
| Ta = reverse(SWO["temp"][:, :, 8, :], dims=2) | ||
| ua = reverse(SWO["u"][:, :, 8, :], dims=2) | ||
| va = reverse(SWO["v"][:, :, 8, :], dims=2) | ||
| sp = sqrt.(ua.^2 + va.^2) | ||
|
|
||
| SST = FieldTimeSeries("ocean_surface_fields.jld2", "T") | ||
| SSU = FieldTimeSeries("ocean_surface_fields.jld2", "u") | ||
| SSV = FieldTimeSeries("ocean_surface_fields.jld2", "v") | ||
|
|
||
| SIU = FieldTimeSeries("sea_ice_fields.jld2", "u") | ||
| SIV = FieldTimeSeries("sea_ice_fields.jld2", "v") | ||
| SIA = FieldTimeSeries("sea_ice_fields.jld2", "ℵ") | ||
|
|
||
| Qcao = FieldTimeSeries("intercomponent_fluxes.jld2", "Qcao") | ||
| Qvao = FieldTimeSeries("intercomponent_fluxes.jld2", "Qvao") | ||
|
|
||
| uotmp = Field{Face, Center, Nothing}(SST.grid) | ||
| votmp = Field{Center, Face, Nothing}(SST.grid) | ||
|
|
||
| uitmp = Field{Face, Center, Nothing}(SST.grid) | ||
| vitmp = Field{Center, Face, Nothing}(SST.grid) | ||
| atmp = Field{Center, Center, Nothing}(SST.grid) | ||
|
|
||
| sotmp = Field(sqrt(uotmp^2 + votmp^2)) | ||
| sitmp = Field(sqrt(uitmp^2 + vitmp^2) * atmp) | ||
|
|
||
| iter = Observable(1) | ||
| san = @lift sp[:, :, $iter] | ||
| son = @lift begin | ||
| set!(uotmp, SSU[$iter * 2]) | ||
| set!(votmp, SSV[$iter * 2]) | ||
| compute!(sotmp) | ||
| interior(sotmp, :, :, 1) | ||
| end | ||
|
|
||
| ssn = @lift begin | ||
| set!(uitmp, SIU[$iter * 2]) | ||
| set!(vitmp, SIV[$iter * 2]) | ||
| set!(atmp, SIA[$iter * 2]) | ||
| compute!(sitmp) | ||
| interior(sitmp, :, :, 1) | ||
| end | ||
|
|
||
| fig = Figure(size = (1200, 800)) | ||
| ax2 = Axis(fig[1, 1], title = "Surface speed, atmosphere (m/s)") | ||
| hm2 = heatmap!(ax2, san; colormap = :deep) | ||
| ax1 = Axis(fig[1, 2], title = "Surface speed, ocean (m/s)") | ||
| hm = heatmap!(ax1, son; colormap = :deep) | ||
| ax3 = Axis(fig[1, 3], title = "Surface speed, sea-ice (m/s)") | ||
| hm = heatmap!(ax3, ssn; colormap = :deep) | ||
|
|
||
| record(fig, "surface_speeds.mp4", iter, framerate = 15) do i | ||
| iter[] = i | ||
| endnothing #hide | ||
|
|
||
| #  | ||
|
|
||
| Tan = @lift Ta[:, :, $iter] | ||
| Ton = @lift interior(SST[$iter * 2], :, :, 1) | ||
| Qcn = @lift interior(Qcao[$iter * 2], :, :, 1) | ||
| Qvn = @lift interior(Qvao[$iter * 2], :, :, 1) | ||
|
|
||
| fig = Figure(size = (1200, 800)) | ||
| ax1 = Axis(fig[1, 1], title = "2m Temperature, atmosphere (K)") | ||
| hm = heatmap!(ax1, Tan; colormap = :plasma) | ||
| ax2 = Axis(fig[1, 2], title = "Sea Surface Temperature (C)") | ||
| hm2 = heatmap!(ax2, Ton; colormap = :plasma) | ||
| ax3 = Axis(fig[2, 1], title = "Sensible heat flux (W/m²)") | ||
| hm3 = heatmap!(ax3, Qcn; colormap = :balance, colorrange = (-200, 200)) | ||
| ax4 = Axis(fig[2, 2], title = "Latent heat flux (W/m²)") | ||
| hm4 = heatmap!(ax4, Qvn; colormap = :balance, colorrange = (-200, 200)) | ||
|
|
||
| record(fig, "surface_temperature_and_heat_flux.mp4", 1:length(sp[1, 1, :])) do i | ||
| iter[] = i | ||
| end | ||
| nothing #hide | ||
|
|
||
| #  |
19 changes: 19 additions & 0 deletions
19
ext/ClimaOceanSpeedyWeatherExt/ClimaOceanSpeedyWeatherExt.jl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| module ClimaOceanSpeedyWeatherExt | ||
|
|
||
| using OffsetArrays | ||
| using KernelAbstractions | ||
| using Statistics | ||
|
|
||
| import SpeedyWeather | ||
| import ClimaOcean | ||
| import Oceananigans | ||
| import SpeedyWeather.RingGrids | ||
|
|
||
| include("speedy_atmosphere_simulations.jl") | ||
|
|
||
| # TODO: Remove this when we have a proper interface | ||
| # for regridding between tripolar and latitude-longitude grids | ||
| include("bilinear_interpolator.jl") | ||
| include("speedy_weather_exchanger.jl") | ||
|
|
||
| end # module ClimaOceanSpeedyWeatherExt |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
--check-bounds=no😱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.
😅 just checking the speed of the solution. In any case, this is an example build, not a testing pipeline, so we really want to have it as fast as possible.