supergrid_top_row_folds Function

public pure function supergrid_top_row_folds(sg_x, sg_y) result(folds)

.true. iff the supergrid’s top node row is a TRIPOLAR FOLD LINE: every node m coincides geographically with its mirror nxp + 1 - m (MOM6’s fold pairing, T(i, nj+1) = T(ni+1-i, nj)). Points are compared as unit vectors on the sphere, so longitude is modulo 360 and irrelevant at the geographic pole (the OM_1deg fold row crosses 90N with its two copies stored at longitudes 180 deg apart). A lon-lat top row fails this everywhere except at the self-conjugate middle node, so the test cannot be passed by accident. Tolerance: a 1e-7 chord (~0.6 m on the Earth; MOM6 mosaics pair to round-off).

Arguments

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

Node longitude (degrees), (nxp, nyp).

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

Node latitude (degrees), (nxp, nyp).

Return Value logical


Calls

proc~~supergrid_top_row_folds~~CallsGraph proc~supergrid_top_row_folds supergrid_top_row_folds none~unit_vector unit_vector proc~supergrid_top_row_folds->none~unit_vector

Called by

proc~~supergrid_top_row_folds~~CalledByGraph proc~supergrid_top_row_folds supergrid_top_row_folds proc~metrics_fill_from_supergrid metrics_fill_from_supergrid proc~metrics_fill_from_supergrid->proc~supergrid_top_row_folds proc~configure_ocean_metrics configure_ocean_metrics proc~configure_ocean_metrics->proc~metrics_fill_from_supergrid proc~engine_setup engine_setup proc~engine_setup->proc~configure_ocean_metrics proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~rdb_ocean_create_finalize rdb_ocean_create_finalize proc~rdb_ocean_create_finalize->proc~complete_ocean_create proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~complete_ocean_create

Variables

Type Visibility Attributes Name Initial
real(kind=wp), private, parameter :: TOL_CHORD = 1.0e-7_wp
integer, private :: m
integer, private :: mm
integer, private :: nxp
integer, private :: nyp
real(kind=wp), private :: p(3)
real(kind=wp), private :: q(3)

Functions

pure function unit_vector(lat_deg, lon_deg) result(v)

Arguments

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

Return Value real(kind=wp), (3)


Source Code

   pure function supergrid_top_row_folds(sg_x, sg_y) result(folds)
      !! `.true.` iff the supergrid's top node row is a TRIPOLAR FOLD LINE:
      !! every node `m` coincides geographically with its mirror
      !! `nxp + 1 - m` (MOM6's fold pairing, `T(i, nj+1) = T(ni+1-i, nj)`).
      !! Points are compared as unit vectors on the sphere, so longitude is
      !! modulo 360 and irrelevant at the geographic pole (the OM_1deg fold
      !! row crosses 90N with its two copies stored at longitudes 180 deg
      !! apart).  A lon-lat top row fails this everywhere except at the
      !! self-conjugate middle node, so the test cannot be passed by
      !! accident.  Tolerance: a 1e-7 chord (~0.6 m on the Earth; MOM6
      !! mosaics pair to round-off).
      real(wp), intent(in) :: sg_x(:, :)
         !! Node longitude (degrees), `(nxp, nyp)`.
      real(wp), intent(in) :: sg_y(:, :)
         !! Node latitude (degrees), `(nxp, nyp)`.
      logical :: folds
      integer :: nxp, nyp, m, mm
      real(wp) :: p(3), q(3)
      real(wp), parameter :: TOL_CHORD = 1.0e-7_wp

      nxp = size(sg_x, 1)
      nyp = size(sg_x, 2)
      folds = nxp >= 3
      do m = 1, nxp
         mm = nxp + 1 - m
         p = unit_vector(sg_y(m, nyp), sg_x(m, nyp))
         q = unit_vector(sg_y(mm, nyp), sg_x(mm, nyp))
         if (norm2(p - q) > TOL_CHORD) then
            folds = .false.
            return
         end if
      end do
   contains
      pure function unit_vector(lat_deg, lon_deg) result(v)
         real(wp), intent(in) :: lat_deg, lon_deg
         real(wp) :: v(3)
         v = [cos(lat_deg*DEG2RAD)*cos(lon_deg*DEG2RAD), &
              cos(lat_deg*DEG2RAD)*sin(lon_deg*DEG2RAD), sin(lat_deg*DEG2RAD)]
      end function unit_vector
   end function supergrid_top_row_folds