plm_slope_nonuniform Subroutine

private pure subroutine plm_slope_nonuniform(h_l, h_c, h_r, q_l, q_c, q_r, slope)

Thickness-weighted PLM slope — Colella & Woodward (1984) eq (1.7) with the (1.8) bound, the form MOM6 ships as PLM_slope_cw.

Returns the HALF-jump across the cell (the module’s slope convention: q_hat(xi) = q + slope*(2*xi - 1)), i.e. half CW84’s delta a_j. For a profile linear in z the unlimited estimate is exactly a*h_c at ANY thickness triple, and the bound 2*min(q_c - q_min, q_max - q_c) is then a*min(h_l+h_c, h_c+h_r) which never bites — so the reconstruction is linear-exact.

This is NOT the shipped formula’s equal-thickness limit, and the difference is deliberate: on a uniform column (1.7) collapses to the CENTRED difference 0.5*(dq_l + dq_r) under the (1.8) bound, where the shipped kernel uses the strictly more diffusive 0.5*minmod(dq_l, dq_r). So switching the knob on changes the PLM answer even on an unstretched column — it swaps minmod for the CW84 limiter, which is what MOM6 ships as PLM_slope_cw and the only h-weighted PLM slope that is second-order rather than first-order at a smooth extremum. (PPM’s path, by contrast, reduces exactly; see ppm_jump_nonuniform.) Both remain monotone: the (1.8) bound keeps the reconstructed edges inside the three cell means.

H_DIV_EPS (not H_NEGLECT) armours the denominators: every one of them is a SUM of thicknesses, already non-negative by the caller’s precondition, so this is the pure 1/0 role and nothing else.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: h_l

Thickness of the cell below (toward the bed).

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

Thickness of the cell being reconstructed.

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

Thickness of the cell above (toward the surface).

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

Cell mean below.

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

Cell mean here.

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

Cell mean above.

real(kind=wp), intent(out) :: slope

Limited half-jump across the cell.


Called by

proc~~plm_slope_nonuniform~~CalledByGraph proc~plm_slope_nonuniform plm_slope_nonuniform proc~remap_column_plm remap_column_plm proc~remap_column_plm->proc~plm_slope_nonuniform proc~remap_column remap_column proc~remap_column->proc~remap_column_plm proc~remap_column_ppm remap_column_ppm proc~remap_column->proc~remap_column_ppm proc~remap_column_ppm_h4 remap_column_ppm_h4 proc~remap_column->proc~remap_column_ppm_h4 proc~remap_column_pqm remap_column_pqm proc~remap_column->proc~remap_column_pqm proc~remap_column_ppm->proc~remap_column_plm proc~remap_column_ppm_h4->proc~remap_column_plm proc~ocean_remap_tracer_column ocean_remap_tracer_column proc~ocean_remap_tracer_column->proc~remap_column proc~ocean_remap_tracer_field ocean_remap_tracer_field proc~ocean_remap_tracer_field->proc~remap_column proc~remap_column_pqm->proc~remap_column_ppm proc~remap_layer_to_density_impl remap_layer_to_density_impl proc~remap_layer_to_density_impl->proc~remap_column proc~remap_layer_to_vcoord_impl remap_layer_to_vcoord_impl proc~remap_layer_to_vcoord_impl->proc~remap_column proc~remap_tracer_grounded remap_tracer_grounded proc~remap_tracer_grounded->proc~remap_column proc~remap_x_face_grounded remap_x_face_grounded proc~remap_x_face_grounded->proc~remap_column proc~remap_x_face_velocity remap_x_face_velocity proc~remap_x_face_velocity->proc~remap_column proc~remap_y_face_grounded remap_y_face_grounded proc~remap_y_face_grounded->proc~remap_column proc~remap_y_face_velocity remap_y_face_velocity proc~remap_y_face_velocity->proc~remap_column proc~ocean_apply_ale_remap_centres ocean_apply_ale_remap_centres proc~ocean_apply_ale_remap_centres->proc~ocean_remap_tracer_field proc~ocean_apply_ale_remap_faces ocean_apply_ale_remap_faces proc~ocean_apply_ale_remap_faces->proc~remap_x_face_velocity proc~ocean_apply_ale_remap_faces->proc~remap_y_face_velocity proc~ocean_apply_ale_remap_step ocean_apply_ale_remap_step proc~ocean_apply_ale_remap_step->proc~ocean_remap_tracer_field proc~ocean_apply_ale_remap_step->proc~remap_x_face_velocity proc~ocean_apply_ale_remap_step->proc~remap_y_face_velocity proc~ocean_apply_conservative_min_thickness ocean_apply_conservative_min_thickness proc~ocean_apply_conservative_min_thickness->proc~remap_tracer_grounded proc~ocean_apply_conservative_min_thickness->proc~remap_x_face_grounded proc~ocean_apply_conservative_min_thickness->proc~remap_y_face_grounded proc~remap_layer_to_density remap_layer_to_density proc~remap_layer_to_density->proc~remap_layer_to_density_impl proc~remap_layer_to_sigma remap_layer_to_sigma proc~remap_layer_to_sigma->proc~remap_layer_to_vcoord_impl proc~remap_layer_to_z remap_layer_to_z proc~remap_layer_to_z->proc~remap_layer_to_vcoord_impl proc~remap_layer_to_zstar remap_layer_to_zstar proc~remap_layer_to_zstar->proc~remap_layer_to_vcoord_impl proc~ocean_dyn_step_split ocean_dyn_step_split proc~ocean_dyn_step_split->proc~ocean_apply_ale_remap_step proc~run_continuity_chain run_continuity_chain proc~run_continuity_chain->proc~ocean_apply_conservative_min_thickness

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private :: q_max
real(kind=wp), private :: q_min
real(kind=wp), private :: sig_c
real(kind=wp), private :: sig_l
real(kind=wp), private :: sig_r

Source Code

   pure subroutine plm_slope_nonuniform(h_l, h_c, h_r, q_l, q_c, q_r, slope)
      !$acc routine seq
      !! Thickness-weighted PLM slope — Colella & Woodward (1984) eq (1.7)
      !! with the (1.8) bound, the form MOM6 ships as `PLM_slope_cw`.
      !!
      !! Returns the HALF-jump across the cell (the module's `slope`
      !! convention: `q_hat(xi) = q + slope*(2*xi - 1)`), i.e. half CW84's
      !! `delta a_j`.  For a profile linear in `z` the unlimited estimate is
      !! exactly `a*h_c` at ANY thickness triple, and the bound
      !! `2*min(q_c - q_min, q_max - q_c)` is then `a*min(h_l+h_c, h_c+h_r)`
      !! which never bites — so the reconstruction is linear-exact.
      !!
      !! **This is NOT the shipped formula's equal-thickness limit**, and the
      !! difference is deliberate: on a uniform column (1.7) collapses to the
      !! CENTRED difference `0.5*(dq_l + dq_r)` under the (1.8) bound, where
      !! the shipped kernel uses the strictly more diffusive
      !! `0.5*minmod(dq_l, dq_r)`.  So switching the knob on changes the PLM
      !! answer even on an unstretched column — it swaps minmod for the CW84
      !! limiter, which is what MOM6 ships as `PLM_slope_cw` and the only
      !! h-weighted PLM slope that is second-order rather than first-order at
      !! a smooth extremum.  (PPM's path, by contrast, reduces exactly; see
      !! `ppm_jump_nonuniform`.)  Both remain monotone: the (1.8) bound keeps
      !! the reconstructed edges inside the three cell means.
      !!
      !! `H_DIV_EPS` (not `H_NEGLECT`) armours the denominators: every one of
      !! them is a SUM of thicknesses, already non-negative by the caller's
      !! precondition, so this is the pure 1/0 role and nothing else.
      real(wp), intent(in) :: h_l
         !! Thickness of the cell below (toward the bed).
      real(wp), intent(in) :: h_c
         !! Thickness of the cell being reconstructed.
      real(wp), intent(in) :: h_r
         !! Thickness of the cell above (toward the surface).
      real(wp), intent(in) :: q_l
         !! Cell mean below.
      real(wp), intent(in) :: q_c
         !! Cell mean here.
      real(wp), intent(in) :: q_r
         !! Cell mean above.
      real(wp), intent(out) :: slope
         !! Limited half-jump across the cell.

      real(wp) :: sig_l, sig_r, sig_c, q_min, q_max

      sig_l = q_c - q_l
      sig_r = q_r - q_c
      sig_c = (h_c/(h_l + h_c + h_r + H_DIV_EPS))* &
              ((2.0_wp*h_l + h_c)/(h_c + h_r + H_DIV_EPS)*sig_r &
               + (h_c + 2.0_wp*h_r)/(h_l + h_c + H_DIV_EPS)*sig_l)
      if (sig_l*sig_r > 0.0_wp) then
         q_min = min(q_l, q_c, q_r)
         q_max = max(q_l, q_c, q_r)
         slope = 0.5_wp*sign(min(abs(sig_c), &
                                 2.0_wp*min(q_c - q_min, q_max - q_c)), sig_c)
      else
         slope = 0.0_wp
      end if
   end subroutine plm_slope_nonuniform