cavity_melt_columns Subroutine

public pure subroutine cavity_melt_columns(n, T_w, S_w, p_b, u_star, S_i, par, ice, eos, const, T_b, S_b, m_mass, q_ocean, ierr_col)

Data-parallel driver: solve n independent columns.

WHY THIS EXISTS, and it is not only convenience. On the GPU build the whole kernel lives in librdb_core.so, and nvlink cannot resolve a !$acc routine seq device symbol from a SHARED library into a do concurrent compiled in a DIFFERENT translation unit — the test that first tried it failed with nvlink error: Undefined reference to 'rdb_ocean_cavity_melt_cavity_solve_melt_', on the GPU toolchain only (gfortran linked and ran it happily). So the column loop must live in the same object as the routine it calls: HERE, not in the caller. The coupling PR’s cavity kernel should therefore extend this routine (or sit beside it in this module), not write its own do concurrent over cavity_solve_melt in the engine.

No locality clause is needed: every iteration writes only its own i-th elements, and cavity_melt_point keeps the solution bundle inside the callee. Explicit-shape dummies throughout, per the repo’s do concurrent descriptor rule.

mem:separate contract: this routine moves NOTHING. The caller owns the mapping — every one of the ten arrays must already be device-present (!$acc enter data copyin(...) for the five inputs, create(...) for the five outputs) and the results must be pulled back with !$acc update self(...).

HOST routine — it LAUNCHES the kernel, so it carries no !$acc routine seq of its own; cavity_melt_point and everything below it do.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

Number of columns.

real(kind=wp), intent(in) :: T_w(n)

Far-field temperature per column (degC).

real(kind=wp), intent(in) :: S_w(n)

Far-field salinity per column (g/kg).

real(kind=wp), intent(in) :: p_b(n)

Interface pressure per column (Pa).

real(kind=wp), intent(in) :: u_star(n)

Friction velocity per column (m/s).

real(kind=wp), intent(in) :: S_i(n)

Ice salinity per column (g/kg).

type(ocean_cavity_exchange_t), intent(in) :: par

Exchange-law bundle, shared by every column.

type(ocean_cavity_ice_t), intent(in) :: ice

Ice-conduction bundle, shared by every column.

type(eos_t), intent(in) :: eos

Shared EOS handle — the liquidus. Flat POD, by value.

type(ocean_cavity_const_t), intent(in) :: const

Constants bundle, shared by every column.

real(kind=wp), intent(out) :: T_b(n)

Interface temperature per column (degC).

real(kind=wp), intent(out) :: S_b(n)

Interface salinity per column (g/kg).

real(kind=wp), intent(out) :: m_mass(n)

Melt mass flux per column (kg/m^2/s), > 0 melting.

real(kind=wp), intent(out) :: q_ocean(n)

Ocean -> interface heat flux per column (W/m^2).

integer, intent(out) :: ierr_col(n)

CAVITY_MELT_* status PER COLUMN. A column kernel must not take the run down for one bad column, so the failures are counted by the caller, not raised here.


Calls

proc~~cavity_melt_columns~~CallsGraph proc~cavity_melt_columns cavity_melt_columns proc~cavity_melt_point cavity_melt_point proc~cavity_melt_columns->proc~cavity_melt_point proc~cavity_solve_melt cavity_solve_melt proc~cavity_melt_point->proc~cavity_solve_melt proc~cavity_solve_melt_f cavity_solve_melt_f proc~cavity_solve_melt->proc~cavity_solve_melt_f proc~cavity_heat_fluxes cavity_heat_fluxes proc~cavity_solve_melt_f->proc~cavity_heat_fluxes proc~cavity_law_is_implicit cavity_law_is_implicit proc~cavity_solve_melt_f->proc~cavity_law_is_implicit proc~cavity_obukhov_length cavity_obukhov_length proc~cavity_solve_melt_f->proc~cavity_obukhov_length proc~cavity_outer_residual cavity_outer_residual proc~cavity_solve_melt_f->proc~cavity_outer_residual proc~cavity_safe_state cavity_safe_state proc~cavity_solve_melt_f->proc~cavity_safe_state proc~cavity_solution_reset cavity_solution_reset proc~cavity_solve_melt_f->proc~cavity_solution_reset proc~cavity_state_at_x cavity_state_at_x proc~cavity_solve_melt_f->proc~cavity_state_at_x proc~eos_freezing_point eos_freezing_point proc~cavity_solve_melt_f->proc~eos_freezing_point proc~cavity_ice_terms cavity_ice_terms proc~cavity_heat_fluxes->proc~cavity_ice_terms proc~cavity_t_ice cavity_t_ice proc~cavity_heat_fluxes->proc~cavity_t_ice proc~cavity_l_plus_is_neutral cavity_l_plus_is_neutral proc~cavity_outer_residual->proc~cavity_l_plus_is_neutral proc~cavity_safe_state->proc~eos_freezing_point proc~cavity_state_at_x->proc~cavity_safe_state proc~cavity_buoyancy_flux cavity_buoyancy_flux proc~cavity_state_at_x->proc~cavity_buoyancy_flux proc~cavity_exchange_velocities_f cavity_exchange_velocities_f proc~cavity_state_at_x->proc~cavity_exchange_velocities_f proc~cavity_l_plus_from_state cavity_l_plus_from_state proc~cavity_state_at_x->proc~cavity_l_plus_from_state proc~cavity_three_equation cavity_three_equation proc~cavity_state_at_x->proc~cavity_three_equation

Variables

Type Visibility Attributes Name Initial
integer, private :: i

Source Code

   pure subroutine cavity_melt_columns(n, T_w, S_w, p_b, u_star, S_i, par, ice, eos, &
                                       const, T_b, S_b, m_mass, q_ocean, ierr_col)
      !! Data-parallel driver: solve `n` independent columns.
      !!
      !! WHY THIS EXISTS, and it is not only convenience.  On the GPU
      !! build the whole kernel lives in `librdb_core.so`, and nvlink
      !! cannot resolve a `!$acc routine seq` device symbol from a SHARED
      !! library into a `do concurrent` compiled in a DIFFERENT
      !! translation unit — the test that first tried it failed with
      !! `nvlink error: Undefined reference to
      !! 'rdb_ocean_cavity_melt_cavity_solve_melt_'`, on the GPU
      !! toolchain only (gfortran linked and ran it happily).  So the
      !! column loop must live in the same object as the routine it
      !! calls: HERE, not in the caller.  The coupling PR's cavity kernel
      !! should therefore extend this routine (or sit beside it in this
      !! module), not write its own `do concurrent` over
      !! `cavity_solve_melt` in the engine.
      !!
      !! No locality clause is needed: every iteration writes only its
      !! own `i`-th elements, and `cavity_melt_point` keeps the solution
      !! bundle inside the callee.  Explicit-shape dummies throughout,
      !! per the repo's `do concurrent` descriptor rule.
      !!
      !! `mem:separate` contract: this routine moves NOTHING.  The caller
      !! owns the mapping — every one of the ten arrays must already be
      !! device-present (`!$acc enter data copyin(...)` for the five
      !! inputs, `create(...)` for the five outputs) and the results must
      !! be pulled back with `!$acc update self(...)`.
      !!
      !! HOST routine — it LAUNCHES the kernel, so it carries no
      !! `!$acc routine seq` of its own; `cavity_melt_point` and
      !! everything below it do.
      integer, intent(in) :: n
         !! Number of columns.
      real(wp), intent(in) :: T_w(n)
         !! Far-field temperature per column (degC).
      real(wp), intent(in) :: S_w(n)
         !! Far-field salinity per column (g/kg).
      real(wp), intent(in) :: p_b(n)
         !! Interface pressure per column (Pa).
      real(wp), intent(in) :: u_star(n)
         !! Friction velocity per column (m/s).
      real(wp), intent(in) :: S_i(n)
         !! Ice salinity per column (g/kg).
      type(ocean_cavity_exchange_t), intent(in) :: par
         !! Exchange-law bundle, shared by every column.
      type(ocean_cavity_ice_t), intent(in) :: ice
         !! Ice-conduction bundle, shared by every column.
      type(eos_t), intent(in) :: eos
         !! Shared EOS handle — the liquidus.  Flat POD, by value.
      type(ocean_cavity_const_t), intent(in) :: const
         !! Constants bundle, shared by every column.
      real(wp), intent(out) :: T_b(n)
         !! Interface temperature per column (degC).
      real(wp), intent(out) :: S_b(n)
         !! Interface salinity per column (g/kg).
      real(wp), intent(out) :: m_mass(n)
         !! Melt mass flux per column (kg/m^2/s), > 0 melting.
      real(wp), intent(out) :: q_ocean(n)
         !! Ocean -> interface heat flux per column (W/m^2).
      integer, intent(out) :: ierr_col(n)
         !! `CAVITY_MELT_*` status PER COLUMN.  A column kernel must not
         !! take the run down for one bad column, so the failures are
         !! counted by the caller, not raised here.
      integer :: i

      do concurrent(i=1:n)
         call cavity_melt_point(T_w(i), S_w(i), p_b(i), u_star(i), S_i(i), par, ice, &
                                eos, const, T_b(i), S_b(i), m_mass(i), q_ocean(i), &
                                ierr_col(i))
      end do
   end subroutine cavity_melt_columns