rdb_ice_snow Module

Complements rdb_ice_mass%ice_snow_accumulate (the on-ice snow add): the share of &ocean_ice_nml snowfall that lands where there is no ice (open water at ncat>1, ice-free cells at ncat==1, and any category that fails the column’s own entry gate, m_ice(i,j,c) > ICE_RHO_ICE*H_VANISHED) does not accumulate — it melts on contact with seawater. This module delivers that mass’s latent heat + virtual freshening to the ocean through the EXISTING heat_flux_diag/salt_flux_diag contributor seam (rdb_ice_thermo_driver.F90’s ordering contract), the same one ice_frazil_uptake and the melt-side reduce kernels already use. Without this, snowfall > 0 over open water would silently annihilate mass and energy (the sw_thru failure mode, PLAN_PR26_snowfall.md §2 / roadmap §5 trap 15).

Physics (PLAN_PR26_snowfall.md §3). Per unit CELL area, the mass delivered to the ocean over the thermo window is m_ocn = snow_part_ocn * atm_fprec * dt_therm [kg/m^2] It arrives as fresh solid at 0 degC, specific enthalpy enth_fall = ice_enth_from_ts(0, 0) = ICE_ENTH_LIQ_0 - ICE_LAT_FUS = -3.34e5 J/kg (SIS2’s “-LI” convention for frozen precip entering the ocean, SIS_sum_output.F90:783), module constant ENTH_SNOWFALL below. Bringing it to the ocean’s own liquid enthalpy enth_ocean = ice_enthalpy_liquid(sst, s_surf) costs the ocean dE = m_ocn*(enth_ocean - ENTH_SNOWFALL) [J/m^2], so in the heat_flux_diag sign convention (positive DOWN into the ocean, rdb_ice_thermo_driver.F90:14): heat_flux_diag -= m_ocn(enth_ocean - ENTH_SNOWFALL)/dt_therm and, in the ice model’s existing virtual-salt convention (salt_flux_diag += m_net*(s_surf - S_ice)/dt_therm, m_net positive = freeze), fresh water added to the ocean is m_net = -m_ocn with S_snow = 0: salt_flux_diag -= m_ocnssurf_seam/dt_therm The ocean’s water MASS is not increased – Roundabout’s ocean is a volume-conserving virtual-salt-flux model today, the same convention rdb_ice_frazil_uptake’s docstring states for the freeze side. PR-16 converts this (and the melt/frazil paths) to real mass; see the TODO(PR-16) marker below and this module’s binding seam spec.

Contributor ordering (mandatory, driver-enforced): this module MUST run AFTER ice_thermo_driver_step (which unconditionally zeroes heat_flux_diag and writes the melt-side salt_flux_diag contribution) and BEFORE ice_ocean_brine_flux/ice_ocean_heat_flux (which overwrite Q_salt/Q_heat from salt_flux_diag/ heat_flux_diag) – see rdb_driver.F90’s mandated-order comment block. It ADDS to both diags, never zeroes them (third contributor on heat_flux_diag, after the column; second on salt_flux_diag, after the melt-side reduce).

Binding seam spec (PLAN_PR26_snowfall.md §13, owner: PR-16). ocean_sea_ice_t%fprec_ocn_diag(nx_total, ny_total): real(wp), kg/m^2/s, per unit CELL area, positive = frozen fresh water delivered to the ocean surface, zero on land and fully ice-covered cells. SCRATCH: zeroed + rewritten every thermo window by this module; not restart-carried; device-mapped copyin by ocean_sea_ice_enter_data_impl. When PR-16 makes ice<->ocean mass real, it consumes fprec_ocn_diag as a net_massin source at h_layer(:,:,nz) and MUST remove this module’s virtual-salt term (marked TODO(PR-16) below) or the dilution double-counts; the heat term stays (becomes the heat_content_fprec companion, not a duplicate).


Uses

  • module~~rdb_ice_snow~~UsesGraph module~rdb_ice_snow rdb_ice_snow module~rdb_constants rdb_constants module~rdb_ice_snow->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ice_snow->module~rdb_grid module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_ice_snow->module~rdb_ice_enthalpy module~rdb_ice_state rdb_ice_state module~rdb_ice_snow->module~rdb_ice_state pic_types pic_types module~rdb_constants->pic_types module~rdb_grid->module~rdb_constants module~rdb_ice_enthalpy->module~rdb_constants module~rdb_ice_state->module~rdb_constants module~rdb_ice_state->module~rdb_grid module~rdb_ice_state->module~rdb_ice_enthalpy iso_fortran_env iso_fortran_env module~rdb_ice_state->iso_fortran_env module~rdb_ice_column rdb_ice_column module~rdb_ice_state->module~rdb_ice_column module~rdb_mem_report rdb_mem_report module~rdb_ice_state->module~rdb_mem_report module~rdb_ice_column->module~rdb_constants module~rdb_ice_column->module~rdb_ice_enthalpy module~rdb_ice_mass rdb_ice_mass module~rdb_ice_column->module~rdb_ice_mass module~rdb_ice_optics rdb_ice_optics module~rdb_ice_column->module~rdb_ice_optics module~rdb_mem_report->module~rdb_constants module~rdb_mem_report->iso_fortran_env pic_logger pic_logger module~rdb_mem_report->pic_logger pic_strings pic_strings module~rdb_mem_report->pic_strings module~rdb_ice_mass->module~rdb_constants module~rdb_ice_mass->module~rdb_ice_enthalpy module~rdb_ice_optics->module~rdb_constants module~rdb_ice_optics->module~rdb_ice_enthalpy

Used by

  • module~~rdb_ice_snow~~UsedByGraph module~rdb_ice_snow rdb_ice_snow module~rdb_ocean_engine rdb_ocean_engine module~rdb_ocean_engine->module~rdb_ice_snow module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_engine module~rdb_handle rdb_handle module~rdb_handle->module~rdb_ocean_engine module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_api->module~rdb_handle

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private, parameter :: ENTH_SNOWFALL = ICE_ENTH_LIQ_0-ICE_LAT_FUS

Specific enthalpy of frozen precipitation entering the ocean (J/kg) – ice_enth_from_ts(0, 0) evaluated in closed form (fresh water, T<=0: (ICE_ENTH_LIQ_0 - ICE_LAT_FUS) + ICE_CP_ICE*0). SIS2’s “-LI” convention (SIS_sum_output.F90:783).


Subroutines

public pure subroutine ice_snowfall_ocean_share(grid, ice, dt_therm)

Outer shim (outer-shim + flat-impl pattern): forward the ice slot’s arrays to the device kernel. Called only when ice%has_snowfall (driver gate, rdb_driver.F90) – default snowfall=0 never reaches this module.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_sea_ice_t), intent(inout) :: ice
real(kind=wp), intent(in) :: dt_therm

Effective thermo timestep (s) – ocean_dyn_t%therm_dt(dt).

private pure subroutine ice_snowfall_ocean_share_impl(snow_part_ocn, atm_fprec, sst_seam, ssurf_seam, fprec_ocn_diag, heat_flux_diag, salt_flux_diag, dt_therm, nghost, nx, ny)

Device kernel over PHYSICAL cells (ghosts excluded). Gated on snow_part_ocn(i,j) > 0 rather than a separate wet_mask arg: ice_snow_part_ocn_fill_impl (rdb_ice_thermo_driver) already zeroes snow_part_ocn on land/dry/fully-ice-covered cells, so that field IS the wet-and-ice-free gate this kernel needs – functionally identical to (and cheaper than) re-deriving a wet_mask > 0.5 test here, and keeps this module’s signature to the (grid, ice, dt_therm) seam (no ms dependency).

Read more…

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: snow_part_ocn(nx,ny)
real(kind=wp), intent(in) :: atm_fprec(nx,ny)
real(kind=wp), intent(in) :: sst_seam(nx,ny)
real(kind=wp), intent(in) :: ssurf_seam(nx,ny)
real(kind=wp), intent(inout) :: fprec_ocn_diag(nx,ny)
real(kind=wp), intent(inout) :: heat_flux_diag(nx,ny)
real(kind=wp), intent(inout) :: salt_flux_diag(nx,ny)
real(kind=wp), intent(in) :: dt_therm
integer, intent(in) :: nghost
integer, intent(in) :: nx
integer, intent(in) :: ny