vmix_split_kd_heat_salt Subroutine

public pure subroutine vmix_split_kd_heat_salt(grid, this, ms)

Analogue of MOM6’s heat/salt diffusivity split. Derives the per-tracer diffusivities from the assembled interior/boundary- layer diffusivity: Kd_heat = Kd_int + Kd_extra_T -> kt Kd_salt = Kd_int + Kd_extra_S -> ks kt holds Kd_int on entry (every contributor writes it). No double-diffusion contributor exists yet, so Kd_extra_{T,S} = 0 and the split reduces to ks := kt => bit-identical. PR-33 extends this to ks = kt + kd_extra_s ; kt = kt + kd_extra_t BOTH computed from the SAME pre-split kt – read kt into a local before writing it, or the kt update poisons the ks update.

vmix_split_kd_heat_salt is not a contributor – it is the last statement before vmix_assemble, always. Any PR adding a kv/kt contributor inserts it ABOVE this split.

Runs over the full k = 1..nz+1 range (not 2..nz): kt’s boundary interfaces are zeroed every stage by vmix_compute_pp81, so an all-k copy reproduces ks’s init-time boundary zeros exactly and keeps the closed-BC invariant true by construction.

Arguments

Type IntentOptional Attributes Name
type(hgrid_t), intent(in) :: grid
type(ocean_vmix_t), intent(inout) :: this
type(multilayer_state_t), intent(in) :: ms

Calls

proc~~vmix_split_kd_heat_salt~~CallsGraph proc~vmix_split_kd_heat_salt vmix_split_kd_heat_salt proc~vmix_split_ddiff_eos_impl vmix_split_ddiff_eos_impl proc~vmix_split_kd_heat_salt->proc~vmix_split_ddiff_eos_impl proc~vmix_split_ddiff_impl vmix_split_ddiff_impl proc~vmix_split_kd_heat_salt->proc~vmix_split_ddiff_impl proc~vmix_split_kd_heat_salt_impl vmix_split_kd_heat_salt_impl proc~vmix_split_kd_heat_salt->proc~vmix_split_kd_heat_salt_impl local local proc~vmix_split_ddiff_eos_impl->local proc~eos_buoyancy_coeffs eos_buoyancy_coeffs proc~vmix_split_ddiff_eos_impl->proc~eos_buoyancy_coeffs proc~vmix_split_ddiff_impl->local proc~roquet_spv_point roquet_spv_point proc~eos_buoyancy_coeffs->proc~roquet_spv_point

Called by

proc~~vmix_split_kd_heat_salt~~CalledByGraph proc~vmix_split_kd_heat_salt vmix_split_kd_heat_salt proc~vmix_apply_in_stage vmix_apply_in_stage proc~vmix_apply_in_stage->proc~vmix_split_kd_heat_salt proc~run_stage run_stage proc~run_stage->proc~vmix_apply_in_stage proc~run_stage_split run_stage_split proc~run_stage_split->proc~vmix_apply_in_stage proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step proc~engine_step->proc~ocean_dyn_step_split proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_step proc~rdb_ocean_step rdb_ocean_step proc~rdb_ocean_step->proc~engine_step

Variables

Type Visibility Attributes Name Initial
integer, private :: nx
integer, private :: ny
integer, private :: nz

Source Code

   pure subroutine vmix_split_kd_heat_salt(grid, this, ms)
      !! Analogue of MOM6's heat/salt diffusivity split.  Derives the
      !! per-tracer diffusivities from the assembled interior/boundary-
      !! layer diffusivity:
      !!     Kd_heat = Kd_int + Kd_extra_T  ->  kt
      !!     Kd_salt = Kd_int + Kd_extra_S  ->  ks
      !! `kt` holds Kd_int on entry (every contributor writes it).  No
      !! double-diffusion contributor exists yet, so Kd_extra_{T,S} = 0
      !! and the split reduces to `ks := kt` => bit-identical.  PR-33
      !! extends this to
      !!     ks = kt + kd_extra_s ;  kt = kt + kd_extra_t
      !! BOTH computed from the SAME pre-split kt -- read kt into a
      !! local before writing it, or the kt update poisons the ks
      !! update.
      !!
      !! `vmix_split_kd_heat_salt` is not a contributor -- it is the
      !! last statement before `vmix_assemble`, always.  Any PR adding
      !! a kv/kt contributor inserts it ABOVE this split.
      !!
      !! Runs over the full k = 1..nz+1 range (not 2..nz): `kt`'s
      !! boundary interfaces are zeroed every stage by
      !! `vmix_compute_pp81`, so an all-k copy reproduces `ks`'s
      !! init-time boundary zeros exactly and keeps the closed-BC
      !! invariant true by construction.
      type(hgrid_t), intent(in) :: grid
      type(ocean_vmix_t), intent(inout) :: this
      type(multilayer_state_t), intent(in) :: ms

      integer :: nx, ny, nz

      nx = grid%nx_total
      ny = grid%ny_total
      nz = ms%nz_ml

      if (this%ddiff_enable .and. this%buoyancy_coeffs == BUOY_COEFFS_EOS) then
         ! E4: same closure, but α/β come from the ACTIVE EOS at each
         ! interface's own (T, S, p) instead of the scalar pair.  A
         ! SEPARATE impl, deliberately, not a branch inside the collapsed
         ! one: the in-situ pressure has to be accumulated DOWN a column,
         ! which forces `do concurrent(j, i)` + a serial k sweep, and the
         ! default path must keep its fully-collapsed (i, j, k) launch —
         ! both for its GPU parallelism and so its byte-identity is
         ! structural rather than argued.
         call vmix_split_ddiff_eos_impl(nx, ny, nz + 1, this%kt, this%ks, &
                                        ms%tracers(ms%idx_temperature)%hTr, &
                                        ms%tracers(ms%idx_salinity)%hTr, ms%h_layer, &
                                        ms%p_top, this%eos, this%rho0, &
                                        this%p_top_in_eos, &
                                        this%ddiff_strat_param_max, this%ddiff_kappa_s, &
                                        this%ddiff_exp1, this%ddiff_exp2, &
                                        this%ddiff_param1, this%ddiff_param2, &
                                        this%ddiff_param3, this%ddiff_mol_diff, &
                                        this%ddiff_use_k90)
      else if (this%ddiff_enable) then
         ! Outer shim: dereference the registry tracers (idx 1/2) on the
         ! host and hand the flat top-level arrays to the do-concurrent
         ! impl (array-of-derived-type device indirection rule).
         call vmix_split_ddiff_impl(nx, ny, nz + 1, this%kt, this%ks, &
                                    ms%tracers(ms%idx_temperature)%hTr, &
                                    ms%tracers(ms%idx_salinity)%hTr, ms%h_layer, &
                                    this%eos%alpha_T, this%eos%beta_S, &
                                    this%ddiff_strat_param_max, this%ddiff_kappa_s, &
                                    this%ddiff_exp1, this%ddiff_exp2, &
                                    this%ddiff_param1, this%ddiff_param2, &
                                    this%ddiff_param3, this%ddiff_mol_diff, &
                                    this%ddiff_use_k90)
      else
         call vmix_split_kd_heat_salt_impl(nx, ny, nz + 1, this%kt, this%ks)
      end if
   end subroutine vmix_split_kd_heat_salt