roquet_pcm_dpa_face Subroutine

public 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)

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.

Arguments

Type IntentOptional 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 g * int rho' dz over the layer (Pa).

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

The columns’ own g * int rho' dz over the layer (Pa).

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

MOM6 hWt_LL/LR/RR/RL mass-weighting fractions.

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

MOM6 hWt_LL/LR/RR/RL mass-weighting fractions.

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

MOM6 hWt_LL/LR/RR/RL mass-weighting fractions.

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

MOM6 hWt_LL/LR/RR/RL mass-weighting fractions.

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 g * int rho' dz over the layer (Pa).


Calls

proc~~roquet_pcm_dpa_face~~CallsGraph proc~roquet_pcm_dpa_face roquet_pcm_dpa_face proc~roquet_pcm_dpa_intz roquet_pcm_dpa_intz proc~roquet_pcm_dpa_face->proc~roquet_pcm_dpa_intz rdb_roq_spv_p rdb_roq_spv_p proc~roquet_pcm_dpa_intz->rdb_roq_spv_p rdb_roq_ts_coeffs rdb_roq_ts_coeffs proc~roquet_pcm_dpa_intz->rdb_roq_ts_coeffs

Called by

proc~~roquet_pcm_dpa_face~~CalledByGraph proc~roquet_pcm_dpa_face roquet_pcm_dpa_face proc~compute_fv_mom6_insitu_pcm_impl compute_fv_mom6_insitu_pcm_impl proc~compute_fv_mom6_insitu_pcm_impl->proc~roquet_pcm_dpa_face proc~ocean_pressure_force_compute ocean_pressure_force_compute proc~ocean_pressure_force_compute->proc~compute_fv_mom6_insitu_pcm_impl proc~run_stage run_stage proc~run_stage->proc~ocean_pressure_force_compute proc~run_stage_split run_stage_split proc~run_stage_split->proc~ocean_pressure_force_compute proc~ocean_dyn_step ocean_dyn_step proc~ocean_dyn_step->proc~run_stage proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~run_stage_split proc~engine_step engine_step proc~engine_step->proc~ocean_dyn_step proc~engine_step->proc~ocean_dyn_step_split

Variables

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

Source Code

   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