Persistent EVP-rheology scratch (SIS2 C-grid dynamics), hung off
ocean_sea_ice_t as the evp_ws slot — eagerly allocated in the
ice state’s init and GPU-mapped via enter_data, so it matches
the rest of src/core/ocean/ (which carries ZERO module-level
save allocatables — every kernel puts its scratch on a state
DT). Replaces the retired rdb_ice_evp module-level save
workspace + its lazy evp_workspace_ensure/ice_evp_cleanup
lifecycle. Allocated / mapped ONLY when ocean_sea_ice_t%dynamics
is on (the workspace is EVP-dynamics-only).
rdb_ice_evp’s ice_evp_dynamics shim unpacks these components
into the explicit-shape flat-impl args of ice_evp_dynamics_impl
— NEVER read ws%component inside a do concurrent (that triggers
per-launch descriptor copies).
F3 (dummy-argument aliasing safety): mis_in_w/mice_in_w/
ci_in_w are the ice_evp_step gather-INPUT buffers, DELIBERATELY
separate from mis_w/mice_w/ci_w (which ice_evp_dynamics
fills from its intent(in) gathered dummies) — the concentration
gather never writes the same arrays the core reads-then-fills.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | a_u_w(:,:) |
PR 62: face ice concentration, |
||
| real(kind=wp), | public, | allocatable | :: | a_v_w(:,:) |
PR 62: face ice concentration, |
||
| real(kind=wp), | public, | allocatable | :: | ci_in_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | ci_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | del_sh_min_pr_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | del_sh_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mask_q_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mask_t_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mask_u_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mask_v_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mi_ratio_a_q_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mi_u_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mi_v_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mice_in_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mice_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mis_in_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | mis_w(:,:) | |||
| integer, | public | :: | nx | = | 0 |
Cached T-cell x extent (nx_total). |
|
| integer, | public | :: | ny | = | 0 |
Cached T-cell y extent (ny_total). |
|
| real(kind=wp), | public, | allocatable | :: | pres_mice_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | q_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | sh_dd_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | sh_ds_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | sh_dt_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | u_tmp_w(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | zeta_w(:,:) |
Counted allocatable footprint of the EVP scratch (0 when
unallocated, i.e. whenever &ocean_ice_nml dynamics is off).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(evp_workspace_t), | intent(in) | :: | this |
Reverse of init (host deallocation). Idempotent — safe on an
already-clean workspace. Device unmapping is exit_data’s job
(call it first).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(evp_workspace_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(evp_workspace_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(evp_workspace_t), | intent(inout) | :: | this |
Allocate the EVP scratch for an (nx,ny) T-cell domain, zero-init.
Called ONCE per workspace lifetime — from ocean_sea_ice_init
(gated on dynamics) and from the EVP test harness. nx/ny
declared before the arrays that use them is unnecessary here (all
allocatables), but the extents are cached for destroy.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(evp_workspace_t), | intent(inout) | :: | this | |||
| integer, | intent(in) | :: | nx | |||
| integer, | intent(in) | :: | ny |
type :: evp_workspace_t !! Persistent EVP-rheology scratch (SIS2 C-grid dynamics), hung off !! `ocean_sea_ice_t` as the `evp_ws` slot — eagerly allocated in the !! ice state's `init` and GPU-mapped via `enter_data`, so it matches !! the rest of `src/core/ocean/` (which carries ZERO module-level !! `save` allocatables — every kernel puts its scratch on a state !! DT). Replaces the retired `rdb_ice_evp` module-level `save` !! workspace + its lazy `evp_workspace_ensure`/`ice_evp_cleanup` !! lifecycle. Allocated / mapped ONLY when `ocean_sea_ice_t%dynamics` !! is on (the workspace is EVP-dynamics-only). !! !! `rdb_ice_evp`'s `ice_evp_dynamics` shim unpacks these components !! into the explicit-shape flat-impl args of `ice_evp_dynamics_impl` !! — NEVER read `ws%component` inside a `do concurrent` (that triggers !! per-launch descriptor copies). !! !! F3 (dummy-argument aliasing safety): `mis_in_w`/`mice_in_w`/ !! `ci_in_w` are the `ice_evp_step` gather-INPUT buffers, DELIBERATELY !! separate from `mis_w`/`mice_w`/`ci_w` (which `ice_evp_dynamics` !! fills from its `intent(in)` gathered dummies) — the concentration !! gather never writes the same arrays the core reads-then-fills. integer :: nx = 0 !! Cached T-cell x extent (nx_total). integer :: ny = 0 !! Cached T-cell y extent (ny_total). real(wp), allocatable :: mis_w(:, :), mice_w(:, :), ci_w(:, :) real(wp), allocatable :: mis_in_w(:, :), mice_in_w(:, :), ci_in_w(:, :) real(wp), allocatable :: pres_mice_w(:, :), del_sh_min_pr_w(:, :) real(wp), allocatable :: sh_dd_w(:, :), sh_dt_w(:, :) real(wp), allocatable :: zeta_w(:, :), del_sh_w(:, :) real(wp), allocatable :: mask_t_w(:, :) real(wp), allocatable :: mi_u_w(:, :), mask_u_w(:, :), u_tmp_w(:, :) real(wp), allocatable :: mi_v_w(:, :), mask_v_w(:, :) real(wp), allocatable :: sh_ds_w(:, :), mi_ratio_a_q_w(:, :) real(wp), allocatable :: q_w(:, :), mask_q_w(:, :) real(wp), allocatable :: a_u_w(:, :), a_v_w(:, :) !! PR 62: face ice concentration, `a_u_w(i,j) = 0.5*(ci_w(i-1,j) + !! ci_w(i,j))` (same expression/edge convention as !! `evp_mi_face_impl`'s `mi_u`, and as `ice_ocean_stress_flux_impl`'s !! `a_u`). Filled by `evp_mi_face_impl(ci_w, ...)` ONLY when !! `par%a_face_stress`; read ONLY under the same gate — uninitialised !! device memory is unreachable when the knob is off. contains procedure, non_overridable :: init => evp_workspace_init procedure, non_overridable :: enter_data => evp_workspace_enter_data procedure, non_overridable :: exit_data => evp_workspace_exit_data procedure, non_overridable :: destroy => evp_workspace_destroy procedure, non_overridable :: bytes => evp_workspace_bytes end type evp_workspace_t