rdb_ice_init Module

Seeds ocean_sea_ice_t’s six category prognostics (part_size/m_ice/m_snow/enth_ice/enth_snow/sal_ice) from &ocean_ice_ic_nml, so a run can start with a live ice pack instead of growing one from frazil (PLAN_PR24_ice_ic_path.md).

v1 ships two ANALYTIC seeding modes on top of the default no-op: "zero" (default) — early return, touches nothing. "uniform" — scalar concentration/thickness everywhere wet. "latitudes" — SIS2 initialize_concentration_from_latitudes (SIS_state_initialization.F90:489-531): a 0/1 step at arctic_edge/antarctic_edge off metrics%geolatT. Defaults (+-91) => no ice.

Host-side setup code, called ONCE, before ocean_state_enter_data (rdb_driver.F90, between configure_ocean_land_mask and ocean_state_enter_data). No device kernel, no new state array, zero do concurrent. A do concurrent here would either round-trip the (unmapped) host arrays through the device once per loop on -stdpar=gpu (measured 36.9 s regression elsewhere, seed_h_layer_uniform_impl) or read stale device memory — see rdb_ocean_state’s “Plain host loops, NOT do concurrent” precedent.

Mass, not thickness — and per-ICE-area, not per-cell, at ncat>1. The prognostic is m_ice = ICE_RHO_ICE*h_ice [kg/m^2], and at ncat>1 it is per unit ICE-COVERED area (SIS2 mH_ice) — NOT multiplied by conc (module docstring of rdb_ice_state, “:65-86”). At ncat==1 (legacy lumped mode) m_ice is per unit CELL area instead, and part_size is left untouched (part_size(:,:,0)=1 forever — the frozen PR 3b/3c contract).

Category allocation is an ITD fixed point, by construction. The pack’s mass is binned directly against the already-computed ice%mh_lim(1:ncat+1) (filled at slot init by ice_itd_category_bounds) via ice_ic_target_category — the SAME bounds ice_adjust_categories (rdb_ice_itd) uses to restore the ITD every thermo window. Consumers of the ITD MUST read ice%mh_lim, never HLIM_DFLT_TABLE (that table is private to rdb_ice_state) and never a re-derivation from ncat alone — PR-58 may override mh_lim’s VALUES via &ocean_ice_nml hlim, and this module’s IC must stay consistent with whatever init actually computed. ice_adjust_categories applied to an IC-seeded state is therefore a bit-exact no-op (test oracle, not a call site — see “What NOT to take” below).

Enthalpy, not temperature. enth_ice/enth_snow are set from the namelist ice temperature t_ice through the EXACT ice_enth_from_ts inversion (rdb_ice_enthalpy), never assigned directly — the thermodynamic prognostic is specific enthalpy (J/kg), never temperature. sal_ice = s_ice; snow is fresh (ice_enth_from_ts(t_ice, 0.0)).

k-convention. enth_ice/sal_ice are (..., nk_ice) BOTTOM-UP (k=1 = ice bottom/ocean side, k=nk_ice = ice top/atm side) — the opposite of rdb_ice_column’s internal top-down convention. A uniform-t_ice IC is k-symmetric so this cannot be gotten wrong here, but the first person to add a linear top-to-bottom temperature profile must respect it.

What NOT to take from SIS2 (D-list, deliberate divergences): D1 Do NOT call ice_adjust_categories (SIS2’s “seed into cat 1, then adjust_ice_categories” flow) — it is a do concurrent device kernel and the IC runs before enter_data. Bin directly on the host against mh_lim; use the kernel only as a TEST ORACLE. D2 Do NOT seed a placeholder mass (mh_lim(c+1)) into empty categories the way SIS2’s ice_state_mass_init does. Roundabout’s live convention is m_ice = 0 for an empty category (what ice_frazil_uptake_multicat_impl already produces, and what the column entry gate keys on) — adopting SIS2’s placeholder would run a full Winton solve on every empty category of every cell for no change in the answer (part-weighted to zero). D3 Do NOT port ICE_RELATIVE_TEMP_IC/ICE_RELATIVE_SALINITY/ spec_thermo_sal — v1 ships one bulk salinity + one bulk temperature. Deferred. D4 Do NOT port data_override / file-backed ICs — that is PR-14 (v1.1), explicitly out of scope here ("file" is deliberately NOT in the conc_config allowed list).

"zero" (the default) is a stronger no-op than SIS2’s own IC path (SIS2 sets the thermo fields unconditionally): it returns before touching a single array, including sal_ice/enth_ice (already sourced to ICE_BULK_SALINITY/0.0 by ocean_sea_ice_init) — so the restart file bytes are unchanged too.


Uses

  • module~~rdb_ice_init~~UsesGraph module~rdb_ice_init rdb_ice_init module~rdb_constants rdb_constants module~rdb_ice_init->module~rdb_constants module~rdb_grid rdb_grid module~rdb_ice_init->module~rdb_grid module~rdb_ice_column rdb_ice_column module~rdb_ice_init->module~rdb_ice_column module~rdb_ice_enthalpy rdb_ice_enthalpy module~rdb_ice_init->module~rdb_ice_enthalpy module~rdb_ice_state rdb_ice_state module~rdb_ice_init->module~rdb_ice_state module~rdb_multilayer_state rdb_multilayer_state module~rdb_ice_init->module~rdb_multilayer_state module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_ice_init->module~rdb_ocean_metrics pic_types pic_types module~rdb_constants->pic_types module~rdb_grid->module~rdb_constants 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_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_column module~rdb_ice_state->module~rdb_ice_enthalpy iso_fortran_env iso_fortran_env module~rdb_ice_state->iso_fortran_env module~rdb_mem_report rdb_mem_report module~rdb_ice_state->module~rdb_mem_report module~rdb_multilayer_state->module~rdb_constants module~rdb_multilayer_state->module~rdb_grid module~rdb_multilayer_state->iso_fortran_env module~rdb_efp rdb_efp module~rdb_multilayer_state->module~rdb_efp module~rdb_error_ring rdb_error_ring module~rdb_multilayer_state->module~rdb_error_ring module~rdb_multilayer_state->module~rdb_mem_report module~rdb_tracer rdb_tracer module~rdb_multilayer_state->module~rdb_tracer pic_logger pic_logger module~rdb_multilayer_state->pic_logger module~rdb_ocean_metrics->module~rdb_constants module~rdb_ocean_metrics->module~rdb_grid module~rdb_ocean_metrics->iso_fortran_env module~rdb_ocean_metrics->module~rdb_error_ring module~rdb_io_netcdf rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_io_netcdf module~rdb_ocean_metrics->module~rdb_mem_report module~rdb_ocean_bipolar rdb_ocean_bipolar module~rdb_ocean_metrics->module~rdb_ocean_bipolar module~rdb_ocean_fold rdb_ocean_fold module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_status rdb_ocean_status module~rdb_ocean_metrics->module~rdb_ocean_status netcdf netcdf module~rdb_ocean_metrics->netcdf module~rdb_ocean_metrics->pic_logger pic_strings pic_strings module~rdb_ocean_metrics->pic_strings module~rdb_efp->iso_fortran_env ieee_arithmetic ieee_arithmetic module~rdb_efp->ieee_arithmetic module~rdb_error_ring->pic_logger 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 module~rdb_io_netcdf->module~rdb_constants module~rdb_io_netcdf->iso_fortran_env module~rdb_io_netcdf->module~rdb_error_ring module~rdb_io_netcdf->netcdf module~rdb_io_netcdf->pic_logger module~rdb_io_netcdf->pic_strings iso_c_binding iso_c_binding module~rdb_io_netcdf->iso_c_binding module~rdb_mem_report->module~rdb_constants module~rdb_mem_report->iso_fortran_env module~rdb_mem_report->pic_logger module~rdb_mem_report->pic_strings module~rdb_ocean_bipolar->module~rdb_constants module~rdb_ocean_fold->module~rdb_constants module~rdb_tracer->module~rdb_constants module~rdb_tracer->module~rdb_grid module~rdb_tracer->iso_fortran_env module~rdb_tracer->module~rdb_mem_report

Used by

  • module~~rdb_ice_init~~UsedByGraph module~rdb_ice_init rdb_ice_init module~rdb_config rdb_config module~rdb_config->module~rdb_ice_init module~rdb_ocean_engine rdb_ocean_engine module~rdb_ocean_engine->module~rdb_ice_init module~rdb_ocean_engine->module~rdb_config module~rdb_decomp rdb_decomp module~rdb_ocean_engine->module~rdb_decomp module~rdb_ocean_data_forcing rdb_ocean_data_forcing module~rdb_ocean_engine->module~rdb_ocean_data_forcing module~rdb_ocean_data_input rdb_ocean_data_input module~rdb_ocean_engine->module~rdb_ocean_data_input module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_stability_audit rdb_ocean_stability_audit module~rdb_ocean_engine->module~rdb_ocean_stability_audit module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_state rdb_state module~rdb_ocean_engine->module~rdb_state module~rdb_halo rdb_halo module~rdb_ocean_engine->module~rdb_halo module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_fold_exchange rdb_ocean_fold_exchange module~rdb_ocean_engine->module~rdb_ocean_fold_exchange module~rdb_ocean_halo rdb_ocean_halo module~rdb_ocean_engine->module~rdb_ocean_halo module~rdb_ice_evp rdb_ice_evp module~rdb_ocean_engine->module~rdb_ice_evp module~rdb_ice_transport rdb_ice_transport module~rdb_ocean_engine->module~rdb_ice_transport module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_fold_apply rdb_ocean_fold_apply module~rdb_ocean_engine->module~rdb_ocean_fold_apply module~rdb_ocean_halo_state rdb_ocean_halo_state module~rdb_ocean_engine->module~rdb_ocean_halo_state module~rdb_config_schema rdb_config_schema module~rdb_config_schema->module~rdb_config module~rdb_decomp->module~rdb_config module~rdb_driver rdb_driver module~rdb_driver->module~rdb_config module~rdb_driver->module~rdb_ocean_engine module~rdb_driver->module~rdb_ocean_state module~rdb_driver->module~rdb_halo module~rdb_ocean_console_stats rdb_ocean_console_stats module~rdb_driver->module~rdb_ocean_console_stats module~rdb_driver->module~rdb_ocean_dyn module~rdb_handle rdb_handle module~rdb_handle->module~rdb_config module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_ocean_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_config module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_ocean_fold_apply module~rdb_ocean_data_forcing->module~rdb_config module~rdb_ocean_data_forcing->module~rdb_ocean_data_input module~rdb_ocean_data_forcing->module~rdb_ocean_halo_state module~rdb_ocean_data_input->module~rdb_config module~rdb_ocean_setup->module~rdb_config module~rdb_ocean_setup->module~rdb_decomp module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_ocean_setup->module~rdb_halo module~rdb_ocean_setup->module~rdb_ocean_fold_exchange module~rdb_ocean_setup->module~rdb_ocean_halo module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_fold_apply module~rdb_ocean_setup->module~rdb_ocean_halo_state module~rdb_ocean_stability_audit->module~rdb_config module~rdb_ocean_state->module~rdb_config module~rdb_ocean_state->module~rdb_decomp module~rdb_ocean_state->module~rdb_ocean_data_forcing module~rdb_ocean_state->module~rdb_ocean_data_input module~rdb_ocean_z_init rdb_ocean_z_init module~rdb_ocean_state->module~rdb_ocean_z_init module~rdb_ocean_restart_io rdb_ocean_restart_io module~rdb_ocean_state->module~rdb_ocean_restart_io module~rdb_continuity rdb_continuity module~rdb_ocean_state->module~rdb_continuity module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_ocean_z_init->module~rdb_config module~rdb_state->module~rdb_config module~rdb_halo->module~rdb_decomp module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state module~rdb_ocean_fold_exchange->module~rdb_decomp module~rdb_ocean_halo->module~rdb_decomp module~rdb_ocean_restart_io->module~rdb_decomp module~rdb_barotropic_substep rdb_barotropic_substep module~rdb_barotropic_substep->module~rdb_ocean_fold_exchange module~rdb_barotropic_substep->module~rdb_ocean_halo module~rdb_continuity->module~rdb_ocean_fold_exchange module~rdb_continuity->module~rdb_ocean_halo module~rdb_continuity->module~rdb_ocean_fold_apply module~rdb_ice_evp->module~rdb_ocean_halo module~rdb_ice_transport->module~rdb_halo module~rdb_ice_transport->module~rdb_ocean_halo module~rdb_ice_transport->module~rdb_continuity module~rdb_ice_transport->module~rdb_ocean_halo_state module~rdb_ocean_bt_wide rdb_ocean_bt_wide module~rdb_ocean_bt_wide->module~rdb_ocean_halo module~rdb_ocean_bt_wide->module~rdb_barotropic_substep module~rdb_ocean_chksum rdb_ocean_chksum module~rdb_ocean_chksum->module~rdb_halo module~rdb_ocean_console_stats->module~rdb_halo module~rdb_ocean_dyn->module~rdb_ocean_halo module~rdb_ocean_dyn->module~rdb_barotropic_substep module~rdb_ocean_dyn->module~rdb_continuity module~rdb_ocean_dyn->module~rdb_ocean_bt_wide module~rdb_ocean_dyn->module~rdb_ocean_chksum module~rdb_ocean_dyn->module~rdb_ocean_console_stats module~rdb_ocean_dyn->module~rdb_ocean_fold_apply module~rdb_ocean_dyn->module~rdb_ocean_halo_state module~rdb_ocean_fold_apply->module~rdb_ocean_fold_exchange module~rdb_ocean_halo_state->module~rdb_ocean_halo module~rdb_ocean_halo_state->module~rdb_ocean_fold_apply proc~ocean_cavity_mass_step ocean_cavity_mass_step proc~ocean_cavity_mass_step->module~rdb_halo module~rdb_ice_ocean_coupler rdb_ice_ocean_coupler module~rdb_ice_ocean_coupler->module~rdb_ocean_halo_state

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: ICE_IC_CONC_INVALID = -1

Sentinel for an unrecognised conc_config string (fail-loud idiom — a pure function cannot error stop; validate_config turns this into a logger%error).

integer, public, parameter :: ICE_IC_CONC_LATITUDES = 2

SIS2 polar-cap analytic form off metrics%geolatT.

integer, public, parameter :: ICE_IC_CONC_UNIFORM = 1

Scalar concentration/thickness/salinity/temperature everywhere wet.

integer, public, parameter :: ICE_IC_CONC_ZERO = 0

Default: no-op, byte-identical to today.


Derived Types

type, public ::  ice_ic_params_t

Sea-ice IC scalar knob bundle (mirrors ice_evp_params_t). Built ONCE from &ocean_ice_ic_nml via ice_ic_params_from_config; every field a plain scalar (no derived-type deref inside the host loop, same discipline as the EVP params — though this module never runs on-device at all).

Components

Type Visibility Attributes Name Initial
real(kind=wp), public :: antarctic_edge = -91.0_wp

"latitudes" Antarctic edge (degrees_north) — SIS2 ANTARCTIC_ICE_EDGE_IC default (no cell qualifies).

real(kind=wp), public :: arctic_edge = 91.0_wp

"latitudes" Arctic edge (degrees_north) — SIS2 ARCTIC_ICE_EDGE_IC default (no cell qualifies).

real(kind=wp), public :: conc = 0.0_wp

Uniform-mode concentration [0,1] (nondim).

integer, public :: conc_config = ICE_IC_CONC_ZERO

Parsed conc_config enum (ICE_IC_CONC_*).

real(kind=wp), public :: h_ice = 0.0_wp

Ice thickness (m) where seeded — SIS2 ICE_INIT_MASS as a thickness.

real(kind=wp), public :: h_snow = 0.0_wp

Snow thickness (m) where seeded — SIS2 SNOW_INIT_MASS as a thickness.

real(kind=wp), public :: s_ice = ICE_BULK_SALINITY

Ice bulk salinity (PSU) — SIS2 ICE_SALINITY_IC default, which matches ocean_sea_ice_init’s own sal_ice source value, so "uniform" at the default s_ice leaves sal_ice unchanged.

real(kind=wp), public :: t_ice = -4.0_wp

Ice/snow temperature (degC) — SIS2 ICE_TEMPERATURE_IC default.


Functions

public pure function ice_ic_params_from_config(conc_config, conc, h_ice, h_snow, t_ice, s_ice, arctic_edge, antarctic_edge) result(par)

Small constructor — build once from &ocean_ice_ic_nml. Copies ice_evp_params_from_config’s shape; the one difference is conc_config, a STRING here (parsed internally), because the namelist knob is a nml_enum string, not an already-parsed integer.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: conc_config
real(kind=wp), intent(in) :: conc
real(kind=wp), intent(in) :: h_ice
real(kind=wp), intent(in) :: h_snow
real(kind=wp), intent(in) :: t_ice
real(kind=wp), intent(in) :: s_ice
real(kind=wp), intent(in) :: arctic_edge
real(kind=wp), intent(in) :: antarctic_edge

Return Value type(ice_ic_params_t)

public pure function ice_ic_parse_conc_config(s) result(mode)

"zero"/"uniform"/"latitudes" -> ICE_IC_CONC_*; any other string -> ICE_IC_CONC_INVALID (fail-loud idiom: a pure function cannot abort, so validate_config V8 turns the sentinel into a logger%error; nml_enum allowed= is the first line of defence).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: s

Return Value integer

public pure function ice_ic_target_category(m, mh_lim, ncat) result(c)

The IC’s target category for a pack of mass m [kg/m^2] (per-ICE-area, ncat>1 convention): the top bin ncat is UNBOUNDED above (mh_lim(ncat+1) is stored but never used as a cap — ice_adjust_categories’s upward pass stops at c = ncat-1), otherwise the unique c with mh_lim(c) <= m < mh_lim(c+1). Declared ncat before the explicit-shape mh_lim that uses it (decl-order).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: m

Pack mass (kg/m^2, per-ICE-area convention).

real(kind=wp), intent(in) :: mh_lim(ncat+1)

Category lower mass limits (kg/m^2), ice%mh_lim — NEVER a re-derivation from ncat alone (PR-58 may override its values via &ocean_ice_nml hlim).

integer, intent(in) :: ncat

Number of ice thickness categories.

Return Value integer


Subroutines

public pure subroutine ice_init_apply(grid, ms, metrics, ice, par)

Outer shim (outer-shim + flat-impl pattern, mirrors ice_adjust_categories). No-op when the ice slot is not live (is_init gate) or when par%conc_config == ICE_IC_CONC_ZERO (the default-off bit-identity contract — nothing is written, not even sal_ice/enth_ice). ice is intent(inout) (not out): h_lim/mh_lim were filled at init and must survive.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(multilayer_state_t), intent(in) :: ms

READ-ONLY: only wet_mask is read.

type(ocean_metrics_t), intent(in) :: metrics

READ-ONLY: only geolatT is read ("latitudes" mode).

type(ocean_sea_ice_t), intent(inout) :: ice
type(ice_ic_params_t), intent(in) :: par

private pure subroutine ice_init_apply_impl(wet_mask, geolatT, part_size, m_ice, m_snow, enth_ice, enth_snow, sal_ice, mh_lim, conc_config, conc_uniform, h_ice, h_snow, t_ice, s_ice, arctic_edge, antarctic_edge, ncat, nk_ice, nx, ny)

Per-cell seeder. Decl-order: integer dims before the explicit-shape arrays that use them.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: wet_mask(nx,ny)
real(kind=wp), intent(in) :: geolatT(nx,ny)
real(kind=wp), intent(inout) :: part_size(nx,ny,0:ncat)
real(kind=wp), intent(inout) :: m_ice(nx,ny,ncat)
real(kind=wp), intent(inout) :: m_snow(nx,ny,ncat)
real(kind=wp), intent(inout) :: enth_ice(nx,ny,ncat,nk_ice)
real(kind=wp), intent(inout) :: enth_snow(nx,ny,ncat,1)
real(kind=wp), intent(inout) :: sal_ice(nx,ny,ncat,nk_ice)
real(kind=wp), intent(in) :: mh_lim(ncat+1)
integer, intent(in) :: conc_config
real(kind=wp), intent(in) :: conc_uniform
real(kind=wp), intent(in) :: h_ice
real(kind=wp), intent(in) :: h_snow
real(kind=wp), intent(in) :: t_ice
real(kind=wp), intent(in) :: s_ice
real(kind=wp), intent(in) :: arctic_edge
real(kind=wp), intent(in) :: antarctic_edge
integer, intent(in) :: ncat
integer, intent(in) :: nk_ice
integer, intent(in) :: nx
integer, intent(in) :: ny