Gathers mis/mice/ci from the category state (mode-branched,
mirrors PR 4b’s IST->CAS dispatch), pulls the one-step-lagged
ocean surface velocity, and calls ice_evp_dynamics on
ice%u_ice/v_ice/str_d/str_t/str_s/fxoc/fyoc. No-op when the
ice slot is not live or dynamics is off (defence-in-depth; the
driver already gates this call on ice%dynamics).
DEVIATION from SPEC §4.1’s literal signature: par is an
explicit argument here (the spec’s shim signature omits it, but
the shim has no other route to &ocean_ice_nml — the driver
builds par ONCE via ice_evp_params_from_config and passes it
into every call, which is both cheaper and clearer than a hidden
module-level singleton).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(hgrid_t), | intent(in) | :: | grid | |||
| type(ocean_metrics_t), | intent(in) | :: | metrics | |||
| real(kind=wp), | intent(in) | :: | f_corner(:,:) |
Coriolis parameter at corners, shape (nx+1,ny+1) ( |
||
| type(ocean_sea_ice_t), | intent(inout) | :: | ice | |||
| type(multilayer_state_t), | intent(in) | :: | ms | |||
| real(kind=wp), | intent(in) | :: | dt_slow | |||
| type(ice_evp_params_t), | intent(in) | :: | par | |||
| type(ocean_bc_state_t), | intent(in) | :: | bc |
Edge policy: |
||
| real(kind=wp), | intent(in), | optional | :: | dt_transport |
PR 36: the dt the TRANSPORT step will actually consume
( |
|
| integer, | intent(out), | optional | :: | n_trunc |
PR 36: count of ice-bearing faces the final CFL clip touched
( |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| logical, | private | :: | halo_x | ||||
| logical, | private | :: | halo_y | ||||
| integer, | private | :: | nx | ||||
| integer, | private | :: | ny | ||||
| integer, | private | :: | nz |
subroutine ice_evp_step(grid, metrics, f_corner, ice, ms, dt_slow, par, & bc, dt_transport, n_trunc) !! Gathers `mis`/`mice`/`ci` from the category state (mode-branched, !! mirrors PR 4b's IST->CAS dispatch), pulls the one-step-lagged !! ocean surface velocity, and calls `ice_evp_dynamics` on !! `ice%u_ice/v_ice/str_d/str_t/str_s/fxoc/fyoc`. No-op when the !! ice slot is not live or `dynamics` is off (defence-in-depth; the !! driver already gates this call on `ice%dynamics`). !! !! DEVIATION from SPEC §4.1's literal signature: `par` is an !! explicit argument here (the spec's shim signature omits it, but !! the shim has no other route to `&ocean_ice_nml` — the driver !! builds `par` ONCE via `ice_evp_params_from_config` and passes it !! into every call, which is both cheaper and clearer than a hidden !! module-level singleton). type(hgrid_t), intent(in) :: grid type(ocean_metrics_t), intent(in) :: metrics real(wp), intent(in) :: f_corner(:, :) !! Coriolis parameter at corners, shape (nx+1,ny+1) (`coriolis_adv_t%f_corner`). type(ocean_sea_ice_t), intent(inout) :: ice type(multilayer_state_t), intent(in) :: ms real(wp), intent(in) :: dt_slow type(ice_evp_params_t), intent(in) :: par type(ocean_bc_state_t), intent(in) :: bc !! Edge policy: `periodic_x/_y` (wrap) and `has_west/_east/_south/ !! _north` (physical edge vs MPI seam). A ghost band is pinned to !! land only on a physical, non-periodic edge; on a decomposed axis !! the halo fills it (see D6 in the module docstring). real(wp), intent(in), optional :: dt_transport !! PR 36: the dt the TRANSPORT step will actually consume !! (`ocean_dyn%therm_dt(dt)`), NOT this call's `dt_slow` — EVP !! runs every outer step, transport at thermo cadence. Absent => !! `dt_slow` (read only when `par%cfl_trunc > 0`). integer, intent(out), optional :: n_trunc !! PR 36: count of ice-bearing faces the final CFL clip touched !! (`0` when `par%cfl_trunc <= 0`). Mirrors `ice_transport_step`'s !! `ok` idiom — the caller (driver) logs, this module does not. integer :: nx, ny, nz logical :: halo_x, halo_y if (.not. ice%is_init .or. .not. ice%dynamics) then if (present(n_trunc)) n_trunc = 0 return end if ! An axis split across ranks is the halo's: exchange there, and run ! the local periodic wrap only on an axis it does not own. halo_x = ocean_halo_is_decomposed_x() halo_y = ocean_halo_is_decomposed_y() nx = grid%nx_total ny = grid%ny_total nz = ms%nz_ml ! F3: gather into the dedicated INPUT buffers on the workspace slot, ! distinct from the `mis_w`/`mice_w`/`ci_w` that `ice_evp_dynamics` ! fills from these — no dummy-argument aliasing. call ice_cell_concentration_impl(metrics%wet_T, ice%part_size, ice%m_ice, & ice%m_snow, ice%evp_ws%mis_in_w, ice%evp_ws%mice_in_w, & ice%evp_ws%ci_in_w, ice%ncat, nx, ny) call ice_evp_dynamics(grid, metrics, f_corner, ice%evp_ws%mis_in_w, & ice%evp_ws%mice_in_w, ice%evp_ws%ci_in_w, & ms%u_face_x_layer(:, :, nz), ms%v_face_y_layer(:, :, nz), & ice%tau_a_x, ice%tau_a_y, ice%u_ice, ice%v_ice, & ice%str_d, ice%str_t, ice%str_s, ice%fxoc, ice%fyoc, & dt_slow, par, bc%periodic_x, bc%periodic_y, ice%evp_ws, & dt_transport, n_trunc, halo_x=halo_x, halo_y=halo_y, & land_w=bc%has_west .and. .not. bc%periodic_x, & land_e=bc%has_east .and. .not. bc%periodic_x, & land_s=bc%has_south .and. .not. bc%periodic_y, & land_n=bc%has_north .and. .not. bc%periodic_y) end subroutine ice_evp_step