Cross-face 5-point Boole quadrature of the layer dpa for a PCM
column pair under Roquet SpV (intx_dpa / inty_dpa): the Roquet
twin of wright_pcm_dpa_face, and boole_dpa_face_pcm with the
factored vertical rule roquet_pcm_dpa_intz at the three interior
sub-columns (same sub-column T/S / height / thickness
interpolation, same weights and summation order). 3 T/S
polynomials + 15 pressure Horners per face per layer, against 15
full generic-EOS calls.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | e_top_l |
Shallower-interface heights in the left / right column (m). |
||
| real(kind=wp), | intent(in) | :: | e_top_r |
Shallower-interface heights in the left / right column (m). |
||
| real(kind=wp), | intent(in) | :: | dz_l |
Layer thicknesses in the left / right column (m, >= 0). |
||
| real(kind=wp), | intent(in) | :: | dz_r |
Layer thicknesses in the left / right column (m, >= 0). |
||
| real(kind=wp), | intent(in) | :: | t_l |
Layer-mean temperature / salinity in the left / right column. |
||
| real(kind=wp), | intent(in) | :: | t_r |
Layer-mean temperature / salinity in the left / right column. |
||
| real(kind=wp), | intent(in) | :: | s_l |
Layer-mean temperature / salinity in the left / right column. |
||
| real(kind=wp), | intent(in) | :: | s_r |
Layer-mean temperature / salinity in the left / right column. |
||
| real(kind=wp), | intent(in) | :: | dpa_l |
The columns’ own |
||
| real(kind=wp), | intent(in) | :: | dpa_r |
The columns’ own |
||
| real(kind=wp), | intent(in) | :: | hwt_ll |
MOM6 |
||
| real(kind=wp), | intent(in) | :: | hwt_lr |
MOM6 |
||
| real(kind=wp), | intent(in) | :: | hwt_rr |
MOM6 |
||
| real(kind=wp), | intent(in) | :: | hwt_rl |
MOM6 |
||
| real(kind=wp), | intent(in) | :: | rho0 |
Boussinesq pressure-estimate density / anomaly reference. |
||
| real(kind=wp), | intent(in) | :: | rho_ref |
Boussinesq pressure-estimate density / anomaly reference. |
||
| real(kind=wp), | intent(out) | :: | dpa_face |
Along-face mean of |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | acc | ||||
| real(kind=wp), | private | :: | dpa_m | ||||
| real(kind=wp), | private | :: | intz_m | ||||
| integer, | private | :: | m | ||||
| real(kind=wp), | private | :: | wl | ||||
| real(kind=wp), | private | :: | wr | ||||
| real(kind=wp), | private | :: | wtt_l | ||||
| real(kind=wp), | private | :: | wtt_r |
pure subroutine roquet_pcm_dpa_face(e_top_l, e_top_r, dz_l, dz_r, & t_l, t_r, s_l, s_r, dpa_l, dpa_r, & hwt_ll, hwt_lr, hwt_rr, hwt_rl, & rho0, rho_ref, dpa_face) !$acc routine seq !! Cross-face 5-point Boole quadrature of the layer `dpa` for a PCM !! column pair under Roquet SpV (`intx_dpa` / `inty_dpa`): the Roquet !! twin of `wright_pcm_dpa_face`, and `boole_dpa_face_pcm` with the !! factored vertical rule `roquet_pcm_dpa_intz` at the three interior !! sub-columns (same sub-column T/S / height / thickness !! interpolation, same weights and summation order). 3 T/S !! polynomials + 15 pressure Horners per face per layer, against 15 !! full generic-EOS calls. real(wp), intent(in) :: e_top_l, e_top_r !! Shallower-interface heights in the left / right column (m). real(wp), intent(in) :: dz_l, dz_r !! Layer thicknesses in the left / right column (m, >= 0). real(wp), intent(in) :: t_l, t_r, s_l, s_r !! Layer-mean temperature / salinity in the left / right column. real(wp), intent(in) :: dpa_l, dpa_r !! The columns' own `g * int rho' dz` over the layer (Pa). real(wp), intent(in) :: hwt_ll, hwt_lr, hwt_rr, hwt_rl !! MOM6 `hWt_LL/LR/RR/RL` mass-weighting fractions. real(wp), intent(in) :: rho0, rho_ref !! Boussinesq pressure-estimate density / anomaly reference. real(wp), intent(out) :: dpa_face !! Along-face mean of `g * int rho' dz` over the layer (Pa). real(wp) :: wr, wl, wtt_l, wtt_r, dpa_m, intz_m, acc integer :: m acc = 7.0_wp*dpa_l + 7.0_wp*dpa_r ! (`GCC$ unroll`: gfortran unrolls the three sub-columns completely ! before vectorising, so the face loops over this vectorise on the CPU; ! nvfortran keeps the loop, which costs fewer registers on the device.) !GCC$ unroll 3 do m = 2, 4 wr = 0.25_wp*real(m - 1, wp) ! 0 at the left column .. 1 at the right wl = 1.0_wp - wr wtt_l = wl*hwt_ll + wr*hwt_rl wtt_r = wl*hwt_lr + wr*hwt_rr call roquet_pcm_dpa_intz(wtt_l*t_l + wtt_r*t_r, wtt_l*s_l + wtt_r*s_r, & wl*e_top_l + wr*e_top_r, wl*dz_l + wr*dz_r, & rho0, rho_ref, dpa_m, intz_m) if (m == 3) then acc = acc + 12.0_wp*dpa_m else acc = acc + 32.0_wp*dpa_m end if end do dpa_face = acc/90.0_wp end subroutine roquet_pcm_dpa_face