seed_ts_linear_z Subroutine

public subroutine seed_ts_linear_z(ms, cfg, ierr, z_draft)

Seed T and S from the ANALYTIC affine geopotential profiles T(z) = lin_t_ref + lin_dt_dz*z, S(z) = lin_s_ref + lin_ds_dz*z (z positive UP, zero at the z = 0 datum), sampled at each layer centre’s TRUE geopotential depth and written as hTr = value * h_layer.

Opens no file, so — unlike the NetCDF path — it fills the FULL array INCLUDING the ghost rows and the dry columns: the formula is defined everywhere, and a ghost column left on some other profile is the wall-adjacent spurious-density-jump gotcha (CLAUDE.md, “formula bathymetry setters must fill ghost rows”). There is no land_fill_t/_s on this path for the same reason.

NOT pure: it logs one line reporting what it seeded, matching seed_ts_from_zfile. The arithmetic itself is the pure elemental linear_in_z.

Arguments

Type IntentOptional Attributes Name
type(multilayer_state_t), intent(inout) :: ms
type(ocean_zinit_config_t), intent(in) :: cfg
integer, intent(out), optional :: ierr

Non-zero on a malformed z_draft when present; absent behaves like the rest of the seed path (error stop).

real(kind=wp), intent(in), optional :: z_draft(:,:)

Ice-base depth (m, positive-down), FULL ghosted (nx_total, ny_total) shape. Absent ⇒ open ocean.


Calls

proc~~seed_ts_linear_z~~CallsGraph proc~seed_ts_linear_z seed_ts_linear_z info info proc~seed_ts_linear_z->info proc~build_z_ctr build_z_ctr proc~seed_ts_linear_z->proc~build_z_ctr proc~draft_shape_ok draft_shape_ok proc~seed_ts_linear_z->proc~draft_shape_ok proc~fail fail proc~seed_ts_linear_z->proc~fail proc~linear_in_z linear_in_z proc~seed_ts_linear_z->proc~linear_in_z to_string to_string proc~seed_ts_linear_z->to_string error error proc~fail->error proc~error_ring_push error_ring_push proc~fail->proc~error_ring_push

Called by

proc~~seed_ts_linear_z~~CalledByGraph proc~seed_ts_linear_z seed_ts_linear_z proc~seed_zinit_overlay seed_zinit_overlay proc~seed_zinit_overlay->proc~seed_ts_linear_z proc~ocean_state_seed_from_cfg ocean_state_seed_from_cfg proc~ocean_state_seed_from_cfg->proc~seed_zinit_overlay proc~engine_setup engine_setup proc~engine_setup->proc~ocean_state_seed_from_cfg 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 :: have_draft
integer, private :: i
integer, private :: idx_S
integer, private :: idx_T
integer, private :: j
integer, private :: k
integer, private :: nxt
integer, private :: nyt
integer, private :: nz_ml
real(kind=wp), private :: z_ctr(ms%nz_ml)
real(kind=wp), private :: z_top

Source Code

   subroutine seed_ts_linear_z(ms, cfg, ierr, z_draft)
      !! Seed T and S from the ANALYTIC affine geopotential profiles
      !! `T(z) = lin_t_ref + lin_dt_dz*z`, `S(z) = lin_s_ref +
      !! lin_ds_dz*z` (`z` positive UP, zero at the `z = 0` datum),
      !! sampled at each layer centre's TRUE geopotential depth and
      !! written as `hTr = value * h_layer`.
      !!
      !! Opens no file, so — unlike the NetCDF path — it fills the FULL
      !! array INCLUDING the ghost rows and the dry columns: the formula
      !! is defined everywhere, and a ghost column left on some other
      !! profile is the wall-adjacent spurious-density-jump gotcha
      !! (CLAUDE.md, "formula bathymetry setters must fill ghost rows").
      !! There is no `land_fill_t/_s` on this path for the same reason.
      !!
      !! NOT `pure`: it logs one line reporting what it seeded, matching
      !! `seed_ts_from_zfile`.  The arithmetic itself is the `pure
      !! elemental` `linear_in_z`.
      type(multilayer_state_t), intent(inout) :: ms
      type(ocean_zinit_config_t), intent(in) :: cfg
      integer, intent(out), optional :: ierr
         !! Non-zero on a malformed `z_draft` when present; absent
         !! behaves like the rest of the seed path (`error stop`).
      real(wp), intent(in), optional :: z_draft(:, :)
         !! Ice-base depth (m, positive-down), FULL ghosted
         !! `(nx_total, ny_total)` shape.  Absent ⇒ open ocean.

      integer :: nxt, nyt, nz_ml, idx_S, idx_T, i, j, k
      real(wp) :: z_ctr(ms%nz_ml)
      real(wp) :: z_top
      logical :: have_draft

      have_draft = present(z_draft)
      if (have_draft) then
         if (.not. draft_shape_ok(z_draft, ms)) then
            call fail("ocean_zinit: z_draft must be the FULL ghosted "// &
                      "(nx_total, ny_total) array, matching h_layer", &
                      ierr, OCEAN_STATUS_ERR_IO)
            return
         end if
      end if

      nxt = size(ms%h_layer, 1)
      nyt = size(ms%h_layer, 2)
      nz_ml = ms%nz_ml
      idx_S = ms%idx_salinity
      idx_T = ms%idx_temperature

      ! Host-side, before enter_data: plain do loops, NOT do concurrent.
      do j = 1, nyt
         do i = 1, nxt
            z_top = 0.0_wp
            if (have_draft) z_top = z_draft(i, j)
            call build_z_ctr(ms%h_layer(i, j, :), nz_ml, z_top, z_ctr)
            if (idx_T > 0) then
               do k = 1, nz_ml
                  ms%tracers(idx_T)%hTr(i, j, k) = &
                     linear_in_z(cfg%lin_t_ref, cfg%lin_dt_dz, z_ctr(k))* &
                     ms%h_layer(i, j, k)
               end do
            end if
            if (idx_S > 0) then
               do k = 1, nz_ml
                  ms%tracers(idx_S)%hTr(i, j, k) = &
                     linear_in_z(cfg%lin_s_ref, cfg%lin_ds_dz, z_ctr(k))* &
                     ms%h_layer(i, j, k)
               end do
            end if
         end do
      end do

      if (have_draft) then
         call logger%info("ocean_zinit: seeded analytic linear-in-z T/S onto "// &
                          to_string(nz_ml)//" model layers, measuring the "// &
                          "geopotential depth from the ice base (cavity draft).")
      else
         call logger%info("ocean_zinit: seeded analytic linear-in-z T/S onto "// &
                          to_string(nz_ml)//" model layers.")
      end if
      call logger%info("ocean_zinit:   T = "//to_string(cfg%lin_t_ref)//" + "// &
                       to_string(cfg%lin_dt_dz)//"*z,  S = "// &
                       to_string(cfg%lin_s_ref)//" + "// &
                       to_string(cfg%lin_ds_dz)//"*z   (z positive UP from z = 0).")
      if (present(ierr)) ierr = OCEAN_STATUS_OK
   end subroutine seed_ts_linear_z