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.
| Type | Intent | Optional | 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) |
|
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | private | :: | i |
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