ocean_sea_ice_init Subroutine

private 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.

Type Bound

ocean_sea_ice_t

Arguments

Type IntentOptional Attributes Name
class(ocean_sea_ice_t), intent(inout) :: this
type(hgrid_t), intent(in) :: grid

Calls

proc~~ocean_sea_ice_init~~CallsGraph proc~ocean_sea_ice_init ocean_sea_ice_t%ocean_sea_ice_init proc~evp_workspace_init evp_workspace_t%evp_workspace_init proc~ocean_sea_ice_init->proc~evp_workspace_init proc~ice_itd_category_bounds ice_itd_category_bounds proc~ocean_sea_ice_init->proc~ice_itd_category_bounds

Source Code

   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