Skip to content

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
wants to merge 23 commits into
base: main
Choose a base branch
from
Open

Add SpeedyWeather extension #463

wants to merge 23 commits into from

Conversation

glwagner
Copy link
Member

@glwagner glwagner commented Apr 9, 2025

This will facilitate coupled simulations with SpeedyWeather using OceanSeaIceModel (whose name may have to change once this extension goes in...)

@glwagner
Copy link
Member Author

glwagner commented Apr 9, 2025

@milankl

Copy link

codecov bot commented Apr 10, 2025

Codecov Report

Attention: Patch coverage is 0% with 36 lines in your changes missing coverage. Please review.

Project coverage is 24.09%. Comparing base (5a7ea23) to head (36a6bdf).

Files with missing lines Patch % Lines
ext/ClimaOceanSpeedyWeatherExt.jl 0.00% 36 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #463      +/-   ##
==========================================
- Coverage   24.44%   24.09%   -0.36%     
==========================================
  Files          43       44       +1     
  Lines        2454     2490      +36     
==========================================
  Hits          600      600              
- Misses       1854     1890      +36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@simone-silvestri
Copy link
Collaborator

here is the preliminary work: glwagner/ClimAdventures.jl#1

@simone-silvestri
Copy link
Collaborator

This was working (simple interpolation atmos -> ocean grid)

    # Get the atmospheric state on the ocean grid
    ua = on_architecture(CPU(), surface_atmosphere_state.u)
    va = on_architecture(CPU(), surface_atmosphere_state.v)
    Ta = on_architecture(CPU(), surface_atmosphere_state.T)
    qa = on_architecture(CPU(), surface_atmosphere_state.q)
    pa = on_architecture(CPU(), surface_atmosphere_state.p)
    Qs = on_architecture(CPU(), surface_atmosphere_state.Qs)
    Qℓ = on_architecture(CPU(), surface_atmosphere_state.Qℓ)
    Mp = on_architecture(CPU(), interpolated_prescribed_freshwater_flux)
    ρf = fluxes.freshwater_density

    λ,  φ,  _ = Oceananigans.Grids.nodes(grid, Center(), Center(), Center(), with_halos=true) 

    λ = Array(vec(on_architecture(CPU(), λ)))
    φ = Array(vec(on_architecture(CPU(), φ)))

    spectral_grid = atmos.model.spectral_grid
    interpolator = RingGrids.AnvilInterpolator(Float32, spectral_grid.Grid, spectral_grid.nlat_half, length(λ))
    RingGrids.update_locator!(interpolator, λ, φ)

    atmosphere_precipitation = (atmos.diagnostic_variables.physics.precip_rate_large_scale .+ 
                                atmos.diagnostic_variables.physics.precip_rate_convection) .* ρf

    RingGrids.interpolate!(vec(view(ua, :, :, 1)), atmos.diagnostic_variables.grid.u_grid[:, end],            interpolator)
    RingGrids.interpolate!(vec(view(va, :, :, 1)), atmos.diagnostic_variables.grid.v_grid[:, end],            interpolator)
    RingGrids.interpolate!(vec(view(Ta, :, :, 1)), atmos.diagnostic_variables.grid.temp_grid[:, end],         interpolator)
    RingGrids.interpolate!(vec(view(qa, :, :, 1)), atmos.diagnostic_variables.grid.humid_grid[:, end],        interpolator)
    RingGrids.interpolate!(vec(view(pa, :, :, 1)), exp.(atmos.diagnostic_variables.grid.pres_grid[:, end]),   interpolator)
    RingGrids.interpolate!(vec(view(Qs, :, :, 1)), atmos.diagnostic_variables.physics.surface_shortwave_down, interpolator)
    RingGrids.interpolate!(vec(view(Qℓ, :, :, 1)), atmos.diagnostic_variables.physics.surface_longwave_down,  interpolator)
    RingGrids.interpolate!(vec(view(Mp, :, :, 1)), atmosphere_precipitation,                                         interpolator)

    surface_atmosphere_state.u  .= ua 
    surface_atmosphere_state.v  .= va 
    surface_atmosphere_state.T  .= Ta 
    surface_atmosphere_state.q  .= qa 
    surface_atmosphere_state.p  .= pa 
    surface_atmosphere_state.Qs .= Qs
    surface_atmosphere_state.Qℓ .= Qℓ

And fluxes

# Regrid the fluxes from the ocean/sea-ice grid to the atmospheric model grid
# This is a _hack_!! (We are performing a double interpolation)
function regrid_fluxes_to_atmospheric_model!(atmos::SpeedyWeather.Simulation, similarity_theory_fields, total_fluxes)
    
    spectral_grid = atmos.model.spectral_grid

    # All the location of these fluxes will change
    Qs = similarity_theory_fields.sensible_heat
    Mv = similarity_theory_fields.water_vapor
    Qu = total_fluxes.ocean.heat.upwelling_radiation 
    interpolator = RingGrids.AnvilInterpolator(Float32, FullClenshawGrid, 90, spectral_grid.npoints)
    londs, latds = RingGrids.get_londlatds(spectral_grid.Grid, spectral_grid.nlat_half)
    RingGrids.update_locator!(interpolator, londs, latds)

    regrid_flux!(atmos.diagnostic_variables.physics.sensible_heat_flux,  Qs, interpolator, weights)
    regrid_flux!(atmos.diagnostic_variables.physics.evaporative_flux,    Mv, interpolator, weights)
    regrid_flux!(atmos.diagnostic_variables.physics.surface_longwave_up, Qu, interpolator, weights)

    return nothing
end

function regrid_flux!(speedy_flux, climaocean_flux, interpolator, weights)
    interpolate!(tmp_field, climaocean_flux, weights) 
    tmp_field = on_architecture(CPU(), interior(tmp_field, :, :, 1))
    
    # This should be solved with conservative remapping?
    tmp_field[isnan.(tmp_field)] .= 0 # We do not have antarctic

    flux = FullClenshawGrid(vec(reverse(tmp_field, dims=2)))
    RingGrids.interpolate!(speedy_flux, flux, interpolator)
    return nothing
end

const SWGExt = Base.get_extension(SpeedyWeather, :SpeedyWeatherGeoMakieExt)

get_cell_matrix(grid::SpeedyWeather.SpectralGrid) = SWGExt.get_faces(grid; add_nans=false)
get_cell_matrix(grid::Oceananigans.AbstractGrid) = OCRExt.compute_cell_matrix(grid, Center(), Center(), nothing)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
get_cell_matrix(grid::Oceananigans.AbstractGrid) = OCRExt.compute_cell_matrix(grid, Center(), Center(), nothing)
compute_cell_matrix(grid::Oceananigans.AbstractGrid) = OCRExt.compute_cell_matrix(grid, Center(), Center(), nothing)

don't name mangle if you don't have to

ConservativeRegridding.regrid!(atmos.diagnostic_variables.physics.sensible_heat_flux, transpose(regridder), vec(interior(Qs)))
ConservativeRegridding.regrid!(atmos.diagnostic_variables.physics.evaporative_flux, transpose(regridder), vec(interior(Mv)))
ConservativeRegridding.regrid!(atmos.diagnostic_variables.physics.surface_longwave_up, transpose(regridder), vec(interior(Qu)))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this really be regridded?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not still not sure what we want to do with the upwelling longwave. We can either compute it in ClimaOcean or pass the temperature to the atmosphere which computes its upwelling radiation.
If we separate radiation it might be easier, but for the moment we can compute it in ClimaOcean and pass it to the atmosphere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess with radiation computed in EarthSystemModel, we will indeed have to regrid the radiative fluxes back to the atmosphere?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, let's start with regridding also the longwave up which might be propedeutic for a radiation computed in the EarthSystemModel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants