vmix_seed_backgrounds Subroutine

private pure subroutine vmix_seed_backgrounds(this, skip_kv)

Seed kv_bg/kt_bg/ks_bg and the kv/kt/ks/kd_bg arrays from the current pp81_nu_bg/pp81_kappa_bg fields, then zero the closed-BC boundary interfaces on kv/ks. Extracted out of ocean_vmix_init (§2E structural invariant: kv_bg == pp81_nu_bg, kt_bg == ks_bg == pp81_kappa_bg, so vmix_assemble’s background floor is a no-op for the shipped PP81 closure) so BOTH the initial seed and the &ocean_vmix_nml pp81_* config-copy re-derive consistently — a bare field copy without this call would leave the assembly floor clamped against the OLD (type-default) background even after a user sets a new one. Requires kv/kt/ks/kd_bg already allocated (true after init; the config-copy call runs strictly after init_from_config).

Type Bound

ocean_vmix_t

Arguments

Type IntentOptional Attributes Name
class(ocean_vmix_t), intent(inout) :: this
logical, intent(in), optional :: skip_kv

PR-2 (bt-rem-from-av-rem, fixed per review): default .false. — the FULL seed always runs (scalars + kv/kt/ks/kd_bg arrays + the kv/ks boundary zero), exactly the historical behaviour. The config-copy call site (configure_ocean_lateral, AFTER engine_setup’s restart read) passes skip_kv = state%vmix%kv_from_restart — .true. ONLY when THIS read actually found vmix_kv in the checkpoint (an older checkpoint without the field, or a cold start, both leave kv_from_restart = .false., so the array still reseeds normally and the run is never left with an uninitialised kv). When skipped, kv is left EXACTLY as the restart read wrote it — no reseed, no boundary re-zero — because a checkpointed kv is a CARRIED field (visc_rem_precompute reads the PREVIOUS stage’s kv before this stage recomputes it) and re-zeroing its boundary rows is not provably idempotent: nothing in this tree asserts every kv-writing closure (PP81/KPP/EPBL/kappa-shear/tidal-mixing/convective adjustment, vmix_assemble) keeps kv(:,:,1) / kv(:,:,nz+1) at exactly 0 throughout a run, so re-asserting it here could diverge a restored run from the continued one it must match bitwise. Restoring the checkpoint verbatim is the only choice that is unconditionally correct.

The FIRST bug report on this knob (then named reseed_arrays) was wrong in a different way: it skipped kt/ks/kd_bg and the boundary zero TOO, so a warm restart lost the background diffusivity entirely (kd_bg is set ONLY here) whenever a user ran with bt_rem_from_visc_rem and a Bryan-Lewis/Henyey background or a closed-BC config. kt/ks/kd_bg are never restart-registry state (no cross-stage read lags them, unlike kv), so they — and the scalar trackers — always reseed from the nml-configured pp81_*, cold or warm, unconditionally.


Called by

proc~~vmix_seed_backgrounds~~CalledByGraph proc~vmix_seed_backgrounds ocean_vmix_t%vmix_seed_backgrounds proc~configure_ocean_lateral configure_ocean_lateral proc~configure_ocean_lateral->proc~vmix_seed_backgrounds proc~ocean_vmix_init ocean_vmix_t%ocean_vmix_init proc~ocean_vmix_init->proc~vmix_seed_backgrounds proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_lateral proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~rdb_ocean_create_finalize rdb_ocean_create_finalize proc~rdb_ocean_create_finalize->proc~complete_ocean_create proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~complete_ocean_create

Variables

Type Visibility Attributes Name Initial
logical, private :: do_skip_kv
integer, private :: nz1

Source Code

   pure subroutine vmix_seed_backgrounds(this, skip_kv)
      !! Seed `kv_bg`/`kt_bg`/`ks_bg` and the `kv`/`kt`/`ks`/`kd_bg` arrays
      !! from the current `pp81_nu_bg`/`pp81_kappa_bg` fields, then zero
      !! the closed-BC boundary interfaces on `kv`/`ks`.  Extracted out of
      !! `ocean_vmix_init` (§2E structural invariant: `kv_bg == pp81_nu_bg`,
      !! `kt_bg == ks_bg == pp81_kappa_bg`, so `vmix_assemble`'s background
      !! floor is a no-op for the shipped PP81 closure) so BOTH the initial
      !! seed and the `&ocean_vmix_nml pp81_*` config-copy re-derive
      !! consistently — a bare field copy without this call would leave
      !! the assembly floor clamped against the OLD (type-default)
      !! background even after a user sets a new one.  Requires
      !! `kv`/`kt`/`ks`/`kd_bg` already allocated (true after `init`; the
      !! config-copy call runs strictly after `init_from_config`).
      class(ocean_vmix_t), intent(inout) :: this
      logical, intent(in), optional :: skip_kv
         !! PR-2 (bt-rem-from-av-rem, fixed per review): default `.false.`
         !! — the FULL seed always runs (scalars + `kv`/`kt`/`ks`/`kd_bg`
         !! arrays + the `kv`/`ks` boundary zero), exactly the historical
         !! behaviour.  The config-copy call site
         !! (`configure_ocean_lateral`, AFTER `engine_setup`'s restart
         !! read) passes `skip_kv = state%vmix%kv_from_restart` — `.true.`
         !! ONLY when THIS read actually found `vmix_kv` in the checkpoint
         !! (an older checkpoint without the field, or a cold start, both
         !! leave `kv_from_restart = .false.`, so the array still reseeds
         !! normally and the run is never left with an uninitialised
         !! `kv`).  When skipped, `kv` is left EXACTLY as the restart read
         !! wrote it — no reseed, no boundary re-zero — because a
         !! checkpointed `kv` is a CARRIED field (`visc_rem_precompute`
         !! reads the PREVIOUS stage's `kv` before this stage recomputes
         !! it) and re-zeroing its boundary rows is not provably
         !! idempotent: nothing in this tree asserts every `kv`-writing
         !! closure (PP81/KPP/EPBL/kappa-shear/tidal-mixing/convective
         !! adjustment, `vmix_assemble`) keeps `kv(:,:,1)` /
         !! `kv(:,:,nz+1)` at exactly 0 throughout a run, so re-asserting
         !! it here could diverge a restored run from the continued one
         !! it must match bitwise. Restoring the checkpoint verbatim is
         !! the only choice that is unconditionally correct.
         !!
         !! The FIRST bug report on this knob (then named `reseed_arrays`)
         !! was wrong in a different way: it skipped `kt`/`ks`/`kd_bg` and
         !! the boundary zero TOO, so a warm restart lost the background
         !! diffusivity entirely (`kd_bg` is set ONLY here) whenever a
         !! user ran with `bt_rem_from_visc_rem` and a Bryan-Lewis/Henyey
         !! background or a closed-BC config.  `kt`/`ks`/`kd_bg` are
         !! never restart-registry state (no cross-stage read lags them,
         !! unlike `kv`), so they — and the scalar trackers — always
         !! reseed from the nml-configured `pp81_*`, cold or warm,
         !! unconditionally.
      logical :: do_skip_kv
      integer :: nz1

      do_skip_kv = .false.
      if (present(skip_kv)) do_skip_kv = skip_kv

      this%kv_bg = this%pp81_nu_bg
      this%kt_bg = this%pp81_kappa_bg
      this%ks_bg = this%pp81_kappa_bg

      this%kt = this%pp81_kappa_bg
      this%ks = this%pp81_kappa_bg
      this%kd_bg = this%pp81_kappa_bg

      ! Zero the closed-BC boundary interfaces on ks unconditionally (ks
      ! is never restart state).
      nz1 = size(this%ks, 3)
      this%ks(:, :, 1) = 0.0_wp
      this%ks(:, :, nz1) = 0.0_wp

      if (do_skip_kv) return

      this%kv = this%pp81_nu_bg
      this%kv(:, :, 1) = 0.0_wp
      this%kv(:, :, nz1) = 0.0_wp
   end subroutine vmix_seed_backgrounds