Cache the grid extents, allocate the frazil (PR 1) + Winton
column (PR 3a) prognostics, and mark the slot live. Allocation
is gated on enable at the parent call site (memory Rule 2),
so an ice-off run never carries these arrays.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_sea_ice_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid |
subroutine ocean_sea_ice_init(this, grid) !! Cache the grid extents, allocate the frazil (PR 1) + Winton !! column (PR 3a) prognostics, and mark the slot live. Allocation !! is gated on `enable` at the parent call site (memory Rule 2), !! so an ice-off run never carries these arrays. class(ocean_sea_ice_t), intent(inout) :: this type(hgrid_t), intent(in) :: grid if (this%nk_ice > ICE_NK_MAX .or. this%nk_ice < 1) then error stop "rdb_ice_state: nk_ice must be in [1, ICE_NK_MAX]" end if if (this%ncat < 1) then error stop "rdb_ice_state: ncat must be >= 1" end if if (ICE_CP_BRINE /= ICE_CP_ICE) then error stop "rdb_ice_state: rdb_ice_column assumes ICE_CP_BRINE == ICE_CP_ICE " & //"(the Newton/false-position branches are not ported)" end if ! PR-58: defence-in-depth — `init` is reachable from tests (and any ! other caller) without going through `validate_config`, which ! already polices `hlim_cfg`'s shape at configure time. if (allocated(this%hlim_cfg)) then if (size(this%hlim_cfg) < 2 .or. size(this%hlim_cfg) > this%ncat + 1) then error stop "rdb_ice_state: hlim_cfg must hold 2..ncat+1 entries" end if end if this%nx_total = grid%nx_total this%ny_total = grid%ny_total allocate (this%frazil_heat(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%heat_budget_frazil(this%nx_total, this%ny_total, 1), source=0.0_wp) allocate (this%part_size(this%nx_total, this%ny_total, 0:this%ncat), source=0.0_wp) this%part_size(:, :, 0) = 1.0_wp allocate (this%m_ice(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%m_snow(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%enth_ice(this%nx_total, this%ny_total, this%ncat, this%nk_ice), & source=0.0_wp) allocate (this%enth_snow(this%nx_total, this%ny_total, this%ncat, 1), source=0.0_wp) allocate (this%sal_ice(this%nx_total, this%ny_total, this%ncat, this%nk_ice), & source=ICE_BULK_SALINITY) allocate (this%m_frozen_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%salt_flux_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%atm_sf0(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%atm_dsfdt(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%atm_sw_dn(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%atm_fprec(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%fb(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%sst_seam(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%ssurf_seam(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%tfw_seam(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%tsurf_out(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%h2o_ocn_to_ice(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%h2o_ice_to_ocn(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%heat_to_ocn(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%sw_thru(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%snow_to_ice(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%heat_flux_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%sw_thru_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%m_melt_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%fprec_ocn_diag(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%h_lim(this%ncat + 1), source=0.0_wp) allocate (this%mh_lim(this%ncat + 1), source=0.0_wp) if (allocated(this%hlim_cfg)) then call ice_itd_category_bounds(this%ncat, this%h_lim, this%mh_lim, hlim_vals=this%hlim_cfg) else call ice_itd_category_bounds(this%ncat, this%h_lim, this%mh_lim) end if allocate (this%fb_part_sum(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%snow_part_ocn(this%nx_total, this%ny_total), source=0.0_wp) ! PR 4b: u_ice/v_ice are unconditional (PR 5 EVP needs them ! regardless of whether category transport is on). allocate (this%u_ice(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%v_ice(this%nx_total, this%ny_total + 1), source=0.0_wp) ! PR 5: EVP stress + tau fields, unconditional (cheap 2-D arrays; ! same allocation contract as u_ice/v_ice — allocated whenever the ! ice slot is live, not gated on `dynamics`). allocate (this%str_d(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%str_t(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%str_s(this%nx_total + 1, this%ny_total + 1), source=0.0_wp) allocate (this%tau_a_x(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%tau_a_y(this%nx_total, this%ny_total + 1), source=0.0_wp) allocate (this%fxoc(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%fyoc(this%nx_total, this%ny_total + 1), source=0.0_wp) ! PR 63: tau_ocn_x/y are unconditional (cheap 2-D arrays, same ! contract as fxoc/fyoc). tau_ocn_valid needs no allocation — its ! default 0.0_wp on the type already means "no blend written yet". allocate (this%tau_ocn_x(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%tau_ocn_y(this%nx_total, this%ny_total + 1), source=0.0_wp) ! PR 5: EVP subcycle scratch, gated on `this%dynamics` (the workspace ! is dynamics-only — same as the retired module `evp_workspace_ensure` ! gating). Rides `ocean_state_enter_data` via this%evp_ws%enter_data. if (this%dynamics) then call this%evp_ws%init(this%nx_total, this%ny_total) end if ! PR 4b: transport workspace, gated on `this%transport` (memory ! Rule 2 — do not pay the per-category face-flux footprint by ! default). if (this%transport) then allocate (this%mca_ice(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%mca_snow(this%nx_total, this%ny_total, this%ncat), source=0.0_wp) allocate (this%uh_ice(this%nx_total + 1, this%ny_total, this%ncat), source=0.0_wp) allocate (this%vh_ice(this%nx_total, this%ny_total + 1, this%ncat), source=0.0_wp) allocate (this%uh_snow(this%nx_total + 1, this%ny_total, this%ncat), source=0.0_wp) allocate (this%vh_snow(this%nx_total, this%ny_total + 1, this%ncat), source=0.0_wp) allocate (this%htot_work(this%nx_total, this%ny_total), source=0.0_wp) allocate (this%hl_x_work(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%hr_x_work(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%hl_y_work(this%nx_total, this%ny_total + 1), source=0.0_wp) allocate (this%hr_y_work(this%nx_total, this%ny_total + 1), source=0.0_wp) allocate (this%uhtot_work(this%nx_total + 1, this%ny_total), source=0.0_wp) allocate (this%vhtot_work(this%nx_total, this%ny_total + 1), source=0.0_wp) allocate (this%tr_flux_x_work(this%nx_total + 1, this%ny_total, this%ncat), source=0.0_wp) allocate (this%tr_flux_y_work(this%nx_total, this%ny_total + 1, this%ncat), source=0.0_wp) end if this%is_init = .true. end subroutine ocean_sea_ice_init