ocean_vcoord_compute_target_h_impl Subroutine

private pure subroutine ocean_vcoord_compute_target_h_impl(this, total_h, eta)

Populate target_h(i,j,k) from the column-total depth (H, constant per column for the ocean path; coastal would pass the bathymetry) and the free-surface anomaly η.

Cases:

VCOORD_EULERIAN_Z — target_h(:,:,k) = H(:,:) · dsig(k). The reference grid that rdb_ocean_vertical_advection pins h_layer to via its cancellation trick. No η dependence — that’s the whole point of the mode.

VCOORD_SIGMA — target_h(:,:,k) = (H + η) · dsig(k). Pure terrain-following.

VCOORD_ZSTAR — MOM6 z* (ocean_vcoord_zstar_target): the z_fixed nominal profile dilated per column by the free-surface stretching, over a partial bed cell and inert bed fillers.

VCOORD_ZSIGMA / VCOORD_ZSTAR_SIGMA — smoothstep blends, see module head comment.

VCOORD_ZSTAR_FULL — walks the per-column z_ref(:, :, 0:nz) table populated by build_zref_full. Surface layer absorbs η; subsurface layers keep their reference thicknesses when the column is at or above reference depth. When the column is shallower than reference (η < 0), bed-side layers vanish to zstar_h_min and the surface trim makes sum(target_h) = H exactly. Mirrors coastal vcoord_target_dz_column_zstar_full.

All cases preserve sum_k target_h(i,j,k) = H + η (or = H for EULERIAN_Z). The remap kernel will rely on this.

Arguments

Type IntentOptional Attributes Name
type(ocean_vcoord_t), intent(inout) :: this
real(kind=wp), intent(in) :: total_h(:,:)

Column-total depth H(i, j) (m).

real(kind=wp), intent(in) :: eta(:,:)

Free-surface anomaly η(i, j) (m).


Calls

proc~~ocean_vcoord_compute_target_h_impl~~CallsGraph proc~ocean_vcoord_compute_target_h_impl ocean_vcoord_compute_target_h_impl proc~ocean_vcoord_geometric_target ocean_vcoord_geometric_target proc~ocean_vcoord_compute_target_h_impl->proc~ocean_vcoord_geometric_target proc~ocean_vcoord_z_fixed_target ocean_vcoord_z_fixed_target proc~ocean_vcoord_compute_target_h_impl->proc~ocean_vcoord_z_fixed_target proc~ocean_vcoord_zstar_target ocean_vcoord_zstar_target proc~ocean_vcoord_compute_target_h_impl->proc~ocean_vcoord_zstar_target local local proc~ocean_vcoord_geometric_target->local proc~ocean_vcoord_z_fixed_target->local proc~ocean_vcoord_zstar_target->local

Called by

proc~~ocean_vcoord_compute_target_h_impl~~CalledByGraph proc~ocean_vcoord_compute_target_h_impl ocean_vcoord_compute_target_h_impl proc~ocean_vcoord_compute_target_h ocean_vcoord_t%ocean_vcoord_compute_target_h proc~ocean_vcoord_compute_target_h->proc~ocean_vcoord_compute_target_h_impl proc~ocean_apply_ale_remap_centres ocean_apply_ale_remap_centres proc~ocean_apply_ale_remap_centres->proc~ocean_vcoord_compute_target_h proc~ocean_apply_ale_remap_step ocean_apply_ale_remap_step proc~ocean_apply_ale_remap_step->proc~ocean_vcoord_compute_target_h proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~ocean_apply_ale_remap_step proc~engine_step engine_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
real(kind=wp), private :: h_nominal

Source Code

   pure subroutine ocean_vcoord_compute_target_h_impl(this, total_h, eta)
      !! Populate `target_h(i,j,k)` from the column-total depth (`H`,
      !! constant per column for the ocean path; coastal would pass
      !! the bathymetry) and the free-surface anomaly `η`.
      !!
      !! Cases:
      !!
      !!   VCOORD_EULERIAN_Z — `target_h(:,:,k) = H(:,:) · dsig(k)`.
      !!     The reference grid that `rdb_ocean_vertical_advection`
      !!     pins `h_layer` to via its cancellation trick.  No η
      !!     dependence — that's the whole point of the mode.
      !!
      !!   VCOORD_SIGMA      — `target_h(:,:,k) = (H + η) · dsig(k)`.
      !!     Pure terrain-following.
      !!
      !!   VCOORD_ZSTAR      — MOM6 z* (`ocean_vcoord_zstar_target`): the
      !!     `z_fixed` nominal profile dilated per column by the free-surface
      !!     stretching, over a partial bed cell and inert bed fillers.
      !!
      !!   VCOORD_ZSIGMA / VCOORD_ZSTAR_SIGMA — smoothstep blends, see
      !!     module head comment.
      !!
      !!   VCOORD_ZSTAR_FULL — walks the per-column `z_ref(:, :, 0:nz)`
      !!     table populated by `build_zref_full`.  Surface layer absorbs
      !!     η; subsurface layers keep their reference thicknesses
      !!     when the column is at or above reference depth.  When the
      !!     column is shallower than reference (η < 0), bed-side
      !!     layers vanish to `zstar_h_min` and the surface trim makes
      !!     sum(target_h) = H exactly.  Mirrors coastal
      !!     `vcoord_target_dz_column_zstar_full`.
      !!
      !! All cases preserve `sum_k target_h(i,j,k) = H + η` (or `= H`
      !! for EULERIAN_Z).  The remap kernel will rely on this.
      type(ocean_vcoord_t), intent(inout) :: this
      ! assumed-shape-ok: cadence-bounded (once per outer ALE step); flat impl
      ! behind the thin ocean_vcoord_compute_target_h class wrapper below.
      real(wp), intent(in) :: total_h(:, :)
         !! Column-total depth H(i, j) (m).
      real(wp), intent(in) :: eta(:, :)  ! assumed-shape-ok: same reason as total_h above
         !! Free-surface anomaly η(i, j) (m).
      real(wp) :: h_nominal

      if (.not. this%is_init) return
      ! Lagrangian / isopycnal: the target IS the current h_layer —
      ! nothing to compute, the ALE remap step is a no-op (see
      ! `ocean_apply_ale_remap_step`).  Return before touching
      ! `target_h` so the caller keeps the live `h_layer`.
      if (this%coord_type == VCOORD_LAGRANGIAN) return

      ! VCOORD_LAGRANGIAN: target is whatever `h_layer` already is.  The
      ! ALE remap is a no-op for this case (see `ocean_apply_ale_remap_step`),
      ! so `target_h` is never read; we can skip the compute entirely to
      ! avoid burning a kernel launch.
      if (this%coord_type == VCOORD_LAGRANGIAN) return

      ! Every loop runs in a flat kernel on explicit-shape / scalar dummies:
      ! no `this%` component and no `associate`-name reaches a
      ! `do concurrent` (ifx's do-concurrent -> OpenMP-target lowering ICEs
      ! on the former; the latter is the shape CLAUDE.md forbids — ifx
      ! evaluates such names as zero, and nvfortran -stdpar=gpu hands a
      ! by-reference one to a device callee as a HOST address, see
      ! `ocean_vcoord_rho_target`).
      if (this%coord_type == VCOORD_Z_FIXED) then
         ! Fixed-z (quasi-geopotential) interfaces with vanishing
         ! layers at BOTH ends: `h_min` fillers below the bed and —
         ! under a rigid top (`z_top > 0`, an ice-shelf cavity) —
         ! `h_min` fillers inside the ice, with a partial cell at each
         ! live end.  See `ocean_vcoord_z_fixed_target`, which owns the
         ! algorithm and is shared with the initial-thickness seed.
         !
         ! When `z_fixed_h_ref = 0` (knob unset) fall back to uniform
         ! `(H + η) · dsig(k)` so tests that omit the knob still get
         ! something sensible: the SIGMA branch of the geometric kernel
         ! evaluates exactly that expression.
         !
         ! A stretched nominal profile (`z_fixed_use_profile`) replaces
         ! `h_nominal` with the per-layer `z_fixed_zi` / `z_fixed_dz`
         ! tables; the uniform path below is untouched.
         h_nominal = 0.0_wp
         if (this%z_fixed_h_ref > 0.0_wp) then
            h_nominal = this%z_fixed_h_ref/real(this%nz_ml, wp)
         end if
         if (this%z_fixed_use_profile .or. h_nominal > 0.0_wp) then
            call ocean_vcoord_z_fixed_target(this%target_h, total_h, eta, this%z_top, &
                                             this%nx_total, this%ny_total, this%nz_ml, &
                                             h_nominal, this%z_fixed_use_profile, &
                                             this%z_fixed_zi, this%z_fixed_dz, &
                                             this%zstar_h_min)
            return
         end if
         call ocean_vcoord_geometric_target(VCOORD_SIGMA, this%nx_total, this%ny_total, &
                                            this%nz_ml, this%target_h, total_h, eta, &
                                            this%dsig, this%z_ref_global, this%z_ref, &
                                            this%zsigma_depth_transition, &
                                            this%zsigma_blend_width, this%zstar_h_min)
         return
      end if
      if (this%coord_type == VCOORD_ZSTAR) then
         ! MOM6 z*: the `z_fixed` nominal profile (uniform `z_fixed_h_ref/nz`
         ! or the stretched `z_fixed_zi` table) dilated by the column's
         ! free-surface stretching.  Same `z_fixed_h_ref = 0` fallback as
         ! `z_fixed` (uniform sigma) for a slot no profile was resolved on.
         h_nominal = 0.0_wp
         if (this%z_fixed_h_ref > 0.0_wp) then
            h_nominal = this%z_fixed_h_ref/real(this%nz_ml, wp)
         end if
         if (this%z_fixed_use_profile .or. h_nominal > 0.0_wp) then
            call ocean_vcoord_zstar_target(this%target_h, total_h, eta, &
                                           this%nx_total, this%ny_total, this%nz_ml, &
                                           h_nominal, this%z_fixed_use_profile, &
                                           this%z_fixed_zi, this%zstar_h_min)
            return
         end if
         call ocean_vcoord_geometric_target(VCOORD_SIGMA, this%nx_total, this%ny_total, &
                                            this%nz_ml, this%target_h, total_h, eta, &
                                            this%dsig, this%z_ref_global, this%z_ref, &
                                            this%zsigma_depth_transition, &
                                            this%zsigma_blend_width, this%zstar_h_min)
         return
      end if
      call ocean_vcoord_geometric_target(this%coord_type, this%nx_total, this%ny_total, &
                                         this%nz_ml, this%target_h, total_h, eta, &
                                         this%dsig, this%z_ref_global, this%z_ref, &
                                         this%zsigma_depth_transition, &
                                         this%zsigma_blend_width, this%zstar_h_min)
   end subroutine ocean_vcoord_compute_target_h_impl