rdb_ocean_fold Module

Discrete tripolar north-fold exchange (Murray 1996), LOCAL to the tile that holds the whole fold row. Pure seam operators only (state orchestration lives in rdb_ocean_fold_apply). Free procedures, explicit-shape dummies, j-outer / i-inner do concurrent.

Decomposition

Every map below reads the mirror point from the SAME array, so it is exact only on a tile that holds the whole fold row: the north-edge rank of a north-south split (px = 1, any py), where nx_phys is the global ni and ny_phys counts the tile’s rows up to the fold line (every map is relative to the tile’s own last row, so no global j offset enters). Callers apply it only there — the gate is the rank-local bc%north_fold (tag .and. has_north); on the other ranks the north ghosts are an MPI seam the halo exchange fills. An east-west split (px > 1) needs the mirror of column i, column ni+1-i, from another rank: every fold site routes that case through the owner-routed exchange of rdb_ocean_fold_exchange instead of these kernels — the state-level dispatchers of rdb_ocean_fold_apply, the barotropic fast loop (two exchanges per substep instead of its inline folds, see barotropic_substep) and the setup-time folds (engine_setup, configure_ocean_land_mask). The fold also reads the nghost rows below the fold line, so the north tile must be at least nghost+1 rows tall, and under px > 1 every tile at least nghost+1 columns wide (both refused at configure).

Roundabout staggering (the load-bearing input to every map below)

Continuous grid coordinates: T-cell (i,j), physical i ∈ 1..ni, j ∈ 1..nj, occupies [i-1,i]×[j-1,j]; storage index = nghost + physical. * T h(i,j) centre (i-1/2, j-1/2) * Cu u(i,j) WEST face (i-1, j-1/2) extent nx+1 * Cv v(i,j) SOUTH face (i-1/2, j-1) extent ny+1 * Bu q(i,j) SW corner (i-1, j-1) extent (nx+1,ny+1) (rdb_multilayer_state u_face_x_layer/v_face_y_layer docstrings; coriolis_adv “zeta_corner(i,j) sits at (i-1/2,j-1/2)” relative to T(i,j); metrics%wet_q “SW corner of T-cell (i,j)”.)

The fold

The fold line is y = nj, the NORTH edge of T-row nj. A point (x, y) north of it is the point (ni - x, 2nj - y) (i-periodic, period ni), reached through a 180° rotation of the local frame: both unit vectors reverse, so a true-vector component (u, v, a face flux) NEGATES and a scalar — and the pseudoscalar vorticity / PV (rotation preserves orientation) — COPIES.

Solving x’ = ni - x, y’ = 2nj - y for each stagger’s storage index: | Stagger | x(i) | y(j) | i-map (storage) | j-map (storage) | fold-line row | |---------|-------|-------|-----------------------|-----------------------|---------------| | T | i-½ | j-½ | i’ = 2ng+ni+1 - i | j’ = 2ng+2nj+1 - j | none | | u (Cu) | i-1 | j-½ | i’ = 2ng+ni+2 - i | j’ = 2ng+2nj+1 - j | none | | v (Cv) | i-½ | j-1 | i’ = 2ng+ni+1 - i | j’ = 2ng+2nj+2 - j | ng+nj+1 | | corner | i-1 | j-1 | i’ = 2ng+ni+2 - i | j’ = 2ng+2nj+2 - j | ng+nj+1 |

T and u points never lie on y = nj, so their exchange is a pure halo fill of rows j > ng+nj. v and corners have a row ON the fold line: storage row ng+nj+1 — the south face of the first ghost row, i.e. the NORTH face of the last physical T-row. (The pre-2026-09 code used jsum = 2ng+2nj, j_fold = ng+nj: MOM6’s NORTH-face / NE-corner rule applied to roundabout’s SOUTH-face / SW-corner storage. It antisymmetrised the south face of the last T-row — an ordinary interior face — and filled the true fold-line face from -v(i', ng+nj-1), so every cell of the last row took an unrelated flux through its north face: the global-tripolar B1 mass leak.)

Cross-check against MOM6 (symmetric memory, pass_vector / FMS mpp_update_domains with a folded north edge, CGRID_NE): MOM6 v(i,J) is the north face of cell j = roundabout v(i,J+1), MOM6 q(I,J) NE corner = roundabout q(I+1,J+1), MOM6 u(I,j) east face = roundabout u(I+1,j). MOM6’s fold maps v(i, nj+d) ← -v(ni+1-i, nj-d), q(I, nj+d) ← q(ni-I, nj-d), u(I, nj+d) ← -u(ni-I, nj+1-d); shifting by the index offsets gives exactly the table above (MOM6’s fold-line row J = nj ↔ roundabout row nj+1).

The duplicated-DOF fold-line row (v and corners)

On row ng+nj+1 the storage slots i and i’ (v: i’ = 2ng+ni+1-i; corner: i’ = 2ng+ni+2-i) are the SAME physical face / vertex seen from the two sides of the fold, with opposite orientation. So a single DOF is stored twice and must satisfy v(i) = -v(i’) (a true normal velocity / normal flux through one edge, which leaves cell (i,nj) northward and ENTERS cell (i’,nj) from its north) and q(i) = q(i’) for scalars/vorticity. The dynamics updates both slots independently; the projection overwrites the WEST half from the (negated) east mirror so the row is exactly (anti)symmetric. This is what makes the cross-fold mass flux telescope: Σ_i F(i, ng+nj+1) pairs off to zero. Self-conjugate slots (i = i’): * v: only when ni is odd (column (ni+1)/2) → 0 (a normal velocity equal to minus itself). ni even (every real tripolar grid) has none. * corner: c = ni/2+1 and c = 1 ≡ ni+1 (periodic images) — the two bipoles. Vector corner components → 0; scalars copy. Rows above the fold line (j > ng+nj+1) are pure mirrored images.

Caller ordering (MANDATORY): periodic-x wrap FIRST, then the fold, so the fold reads already cyclically-wrapped ghost columns at the corners.

All helpers stay pure + do concurrent so they run both on device-mapped arrays (stdpar) and during host setup of metric ghosts.


Uses

  • module~~rdb_ocean_fold~~UsesGraph module~rdb_ocean_fold rdb_ocean_fold module~rdb_constants rdb_constants module~rdb_ocean_fold->module~rdb_constants pic_types pic_types module~rdb_constants->pic_types

Used by

  • module~~rdb_ocean_fold~~UsedByGraph module~rdb_ocean_fold rdb_ocean_fold module~rdb_continuity rdb_continuity module~rdb_continuity->module~rdb_ocean_fold module~rdb_ocean_fold_apply rdb_ocean_fold_apply module~rdb_continuity->module~rdb_ocean_fold_apply module~rdb_ocean_fold_exchange rdb_ocean_fold_exchange module~rdb_continuity->module~rdb_ocean_fold_exchange module~rdb_ocean_metrics rdb_ocean_metrics module~rdb_continuity->module~rdb_ocean_metrics module~rdb_ocean_gm rdb_ocean_gm module~rdb_continuity->module~rdb_ocean_gm module~rdb_ocean_mle rdb_ocean_mle module~rdb_continuity->module~rdb_ocean_mle module~rdb_ocean_fold_apply->module~rdb_ocean_fold module~rdb_ocean_fold_apply->module~rdb_ocean_fold_exchange module~rdb_ocean_fold_exchange->module~rdb_ocean_fold module~rdb_decomp rdb_decomp module~rdb_ocean_fold_exchange->module~rdb_decomp module~rdb_ocean_metrics->module~rdb_ocean_fold module~rdb_ocean_setup rdb_ocean_setup module~rdb_ocean_setup->module~rdb_ocean_fold module~rdb_ocean_setup->module~rdb_ocean_fold_apply module~rdb_ocean_setup->module~rdb_ocean_fold_exchange module~rdb_ocean_setup->module~rdb_ocean_metrics module~rdb_ocean_state rdb_ocean_state module~rdb_ocean_setup->module~rdb_ocean_state module~rdb_coriolis_adv rdb_coriolis_adv module~rdb_ocean_setup->module~rdb_coriolis_adv module~rdb_ocean_bottom_drag rdb_ocean_bottom_drag module~rdb_ocean_setup->module~rdb_ocean_bottom_drag module~rdb_ocean_dyn rdb_ocean_dyn module~rdb_ocean_setup->module~rdb_ocean_dyn module~rdb_ocean_halo_state rdb_ocean_halo_state module~rdb_ocean_setup->module~rdb_ocean_halo_state module~rdb_ocean_horizontal_viscosity rdb_ocean_horizontal_viscosity module~rdb_ocean_setup->module~rdb_ocean_horizontal_viscosity module~rdb_ocean_lateral_mix rdb_ocean_lateral_mix module~rdb_ocean_setup->module~rdb_ocean_lateral_mix module~rdb_ocean_pressure_force rdb_ocean_pressure_force module~rdb_ocean_setup->module~rdb_ocean_pressure_force module~rdb_config rdb_config module~rdb_ocean_setup->module~rdb_config module~rdb_ocean_setup->module~rdb_decomp module~rdb_ocean_state->module~rdb_ocean_fold module~rdb_ocean_state->module~rdb_continuity module~rdb_ocean_state->module~rdb_ocean_metrics module~rdb_ocean_state->module~rdb_coriolis_adv module~rdb_ocean_state->module~rdb_ocean_bottom_drag module~rdb_ocean_cavity_flux rdb_ocean_cavity_flux module~rdb_ocean_state->module~rdb_ocean_cavity_flux module~rdb_ocean_state->module~rdb_ocean_dyn module~rdb_ocean_state->module~rdb_ocean_gm module~rdb_ocean_hdiff_tracer rdb_ocean_hdiff_tracer module~rdb_ocean_state->module~rdb_ocean_hdiff_tracer module~rdb_ocean_state->module~rdb_ocean_horizontal_viscosity module~rdb_ocean_isopycnal_slopes rdb_ocean_isopycnal_slopes module~rdb_ocean_state->module~rdb_ocean_isopycnal_slopes module~rdb_ocean_state->module~rdb_ocean_lateral_mix module~rdb_ocean_meke rdb_ocean_meke module~rdb_ocean_state->module~rdb_ocean_meke module~rdb_ocean_state->module~rdb_ocean_mle module~rdb_ocean_state->module~rdb_ocean_pressure_force module~rdb_ocean_redi rdb_ocean_redi module~rdb_ocean_state->module~rdb_ocean_redi module~rdb_ocean_varmix rdb_ocean_varmix module~rdb_ocean_state->module~rdb_ocean_varmix module~rdb_ocean_wave_speed rdb_ocean_wave_speed module~rdb_ocean_state->module~rdb_ocean_wave_speed module~rdb_ocean_state->module~rdb_config module~rdb_ocean_data_forcing rdb_ocean_data_forcing module~rdb_ocean_state->module~rdb_ocean_data_forcing module~rdb_ocean_state->module~rdb_decomp module~rdb_ocean_data_input rdb_ocean_data_input module~rdb_ocean_state->module~rdb_ocean_data_input module~rdb_ocean_z_init rdb_ocean_z_init module~rdb_ocean_state->module~rdb_ocean_z_init module~rdb_barotropic_coupling rdb_barotropic_coupling module~rdb_barotropic_coupling->module~rdb_ocean_metrics module~rdb_barotropic_coupling->module~rdb_coriolis_adv module~rdb_barotropic_coupling->module~rdb_ocean_bottom_drag module~rdb_barotropic_coupling->module~rdb_ocean_horizontal_viscosity module~rdb_barotropic_coupling->module~rdb_ocean_pressure_force module~rdb_barotropic_substep rdb_barotropic_substep module~rdb_barotropic_substep->module~rdb_ocean_fold_exchange module~rdb_barotropic_substep->module~rdb_ocean_metrics module~rdb_coriolis_adv->module~rdb_ocean_metrics module~rdb_driver rdb_driver module~rdb_driver->module~rdb_ocean_state module~rdb_ocean_console_stats rdb_ocean_console_stats module~rdb_driver->module~rdb_ocean_console_stats module~rdb_driver->module~rdb_ocean_dyn module~rdb_ocean_engine rdb_ocean_engine module~rdb_driver->module~rdb_ocean_engine module~rdb_driver->module~rdb_config module~rdb_handle rdb_handle module~rdb_handle->module~rdb_ocean_state module~rdb_handle->module~rdb_ocean_engine module~rdb_handle->module~rdb_config module~rdb_ice_evp rdb_ice_evp module~rdb_ice_evp->module~rdb_ocean_metrics module~rdb_ice_init rdb_ice_init module~rdb_ice_init->module~rdb_ocean_metrics module~rdb_ice_ocean_coupler rdb_ice_ocean_coupler module~rdb_ice_ocean_coupler->module~rdb_ocean_metrics module~rdb_ice_ocean_coupler->module~rdb_ocean_halo_state module~rdb_ice_transport rdb_ice_transport module~rdb_ice_transport->module~rdb_continuity module~rdb_ice_transport->module~rdb_ocean_metrics module~rdb_ice_transport->module~rdb_ocean_halo_state module~rdb_ocean_api rdb_ocean_api module~rdb_ocean_api->module~rdb_ocean_fold_apply module~rdb_ocean_api->module~rdb_handle module~rdb_ocean_diag_derived rdb_ocean_diag_derived module~rdb_ocean_api->module~rdb_ocean_diag_derived module~rdb_ocean_diag_fills rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_diag_fills module~rdb_ocean_api->module~rdb_ocean_dyn module~rdb_ocean_api->module~rdb_ocean_engine module~rdb_ocean_api->module~rdb_config module~rdb_ocean_halo_width rdb_ocean_halo_width module~rdb_ocean_api->module~rdb_ocean_halo_width module~rdb_ocean_bottom_drag->module~rdb_ocean_metrics module~rdb_ocean_bt_wide rdb_ocean_bt_wide module~rdb_ocean_bt_wide->module~rdb_ocean_metrics module~rdb_ocean_bt_wide->module~rdb_barotropic_substep module~rdb_ocean_cavity_flux->module~rdb_ocean_metrics module~rdb_ocean_console_stats->module~rdb_ocean_metrics module~rdb_ocean_diag_derived->module~rdb_ocean_state module~rdb_ocean_diag_derived->module~rdb_ocean_diag_fills module~rdb_ocean_diag_fills->module~rdb_ocean_state module~rdb_ocean_dyn->module~rdb_continuity module~rdb_ocean_dyn->module~rdb_ocean_fold_apply module~rdb_ocean_dyn->module~rdb_ocean_metrics module~rdb_ocean_dyn->module~rdb_barotropic_coupling module~rdb_ocean_dyn->module~rdb_barotropic_substep module~rdb_ocean_dyn->module~rdb_coriolis_adv module~rdb_ocean_dyn->module~rdb_ocean_bottom_drag module~rdb_ocean_dyn->module~rdb_ocean_bt_wide module~rdb_ocean_dyn->module~rdb_ocean_cavity_flux module~rdb_ocean_dyn->module~rdb_ocean_console_stats module~rdb_ocean_dyn->module~rdb_ocean_gm module~rdb_ocean_dyn->module~rdb_ocean_halo_state module~rdb_ocean_dyn->module~rdb_ocean_hdiff_tracer module~rdb_ocean_dyn->module~rdb_ocean_horizontal_viscosity module~rdb_ocean_dyn->module~rdb_ocean_isopycnal_slopes module~rdb_ocean_ke_probe rdb_ocean_ke_probe module~rdb_ocean_dyn->module~rdb_ocean_ke_probe module~rdb_ocean_dyn->module~rdb_ocean_lateral_mix module~rdb_ocean_dyn->module~rdb_ocean_meke module~rdb_ocean_dyn->module~rdb_ocean_mle module~rdb_ocean_dyn->module~rdb_ocean_pressure_force module~rdb_ocean_dyn->module~rdb_ocean_redi module~rdb_ocean_dyn->module~rdb_ocean_varmix module~rdb_ocean_dyn->module~rdb_ocean_wave_speed module~rdb_ocean_bt_budget_probe rdb_ocean_bt_budget_probe module~rdb_ocean_dyn->module~rdb_ocean_bt_budget_probe module~rdb_ocean_engine->module~rdb_ocean_fold_apply module~rdb_ocean_engine->module~rdb_ocean_fold_exchange module~rdb_ocean_engine->module~rdb_ocean_metrics module~rdb_ocean_engine->module~rdb_ocean_setup module~rdb_ocean_engine->module~rdb_ocean_state module~rdb_ocean_engine->module~rdb_ice_evp module~rdb_ocean_engine->module~rdb_ice_init module~rdb_ocean_engine->module~rdb_ice_ocean_coupler module~rdb_ocean_engine->module~rdb_ice_transport module~rdb_ocean_engine->module~rdb_ocean_cavity_flux module~rdb_ocean_engine->module~rdb_ocean_diag_derived module~rdb_ocean_engine->module~rdb_ocean_diag_fills module~rdb_ocean_engine->module~rdb_ocean_dyn module~rdb_ocean_engine->module~rdb_ocean_halo_state module~rdb_ocean_stability_audit rdb_ocean_stability_audit module~rdb_ocean_engine->module~rdb_ocean_stability_audit module~rdb_ocean_engine->module~rdb_config module~rdb_ocean_engine->module~rdb_ocean_data_forcing module~rdb_ocean_engine->module~rdb_decomp module~rdb_ocean_engine->module~rdb_ocean_data_input module~rdb_state rdb_state module~rdb_ocean_engine->module~rdb_state module~rdb_ocean_gm->module~rdb_ocean_metrics module~rdb_ocean_gm->module~rdb_ocean_isopycnal_slopes module~rdb_ocean_halo_state->module~rdb_ocean_fold_apply module~rdb_ocean_hdiff_tracer->module~rdb_ocean_metrics module~rdb_ocean_horizontal_viscosity->module~rdb_ocean_metrics module~rdb_ocean_horizontal_viscosity->module~rdb_ocean_lateral_mix module~rdb_ocean_isopycnal_slopes->module~rdb_ocean_metrics module~rdb_ocean_ke_probe->module~rdb_ocean_metrics module~rdb_ocean_ke_probe->module~rdb_coriolis_adv module~rdb_ocean_lateral_mix->module~rdb_ocean_metrics module~rdb_ocean_meke->module~rdb_ocean_metrics module~rdb_ocean_meke->module~rdb_ocean_gm module~rdb_ocean_meke->module~rdb_ocean_varmix module~rdb_ocean_meke->module~rdb_ocean_wave_speed module~rdb_ocean_mle->module~rdb_ocean_metrics module~rdb_ocean_pressure_force->module~rdb_ocean_metrics module~rdb_ocean_redi->module~rdb_ocean_metrics module~rdb_ocean_stability_audit->module~rdb_ocean_metrics module~rdb_ocean_stability_audit->module~rdb_config module~rdb_ocean_varmix->module~rdb_ocean_metrics module~rdb_ocean_varmix->module~rdb_ocean_isopycnal_slopes module~rdb_ocean_varmix->module~rdb_ocean_wave_speed module~rdb_ocean_wave_speed->module~rdb_ocean_metrics module~rdb_config->module~rdb_ice_init module~rdb_ocean_bt_budget_probe->module~rdb_coriolis_adv module~rdb_ocean_bt_budget_probe->module~rdb_ocean_bottom_drag module~rdb_ocean_bt_budget_probe->module~rdb_ocean_horizontal_viscosity module~rdb_ocean_bt_budget_probe->module~rdb_ocean_pressure_force module~rdb_ocean_data_forcing->module~rdb_ocean_halo_state module~rdb_ocean_data_forcing->module~rdb_config module~rdb_ocean_data_forcing->module~rdb_ocean_data_input module~rdb_ocean_halo_width->module~rdb_coriolis_adv proc~validate_config validate_config proc~validate_config->module~rdb_coriolis_adv proc~validate_config->module~rdb_ocean_bottom_drag proc~validate_config->module~rdb_ocean_horizontal_viscosity proc~validate_config->module~rdb_ocean_lateral_mix proc~validate_config->module~rdb_ocean_pressure_force module~rdb_config_schema rdb_config_schema module~rdb_config_schema->module~rdb_config module~rdb_decomp->module~rdb_config module~rdb_ocean_data_input->module~rdb_config module~rdb_ocean_z_init->module~rdb_config module~rdb_state->module~rdb_config module~rdb_halo rdb_halo module~rdb_halo->module~rdb_decomp module~rdb_ocean_halo rdb_ocean_halo module~rdb_ocean_halo->module~rdb_decomp module~rdb_ocean_restart_io rdb_ocean_restart_io module~rdb_ocean_restart_io->module~rdb_decomp

Interfaces

public interface fold_north_centre

  • private pure subroutine fold_north_centre_2d(fld, nx_total, ny_total, nx_phys, ny_phys, nghost)

    Fill the north halo of a 2D cell-centred field by the T-fold.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: fld(nx_total,ny_total)

    Cell-centred field, shape (nx_total, ny_total).

    integer, intent(in) :: nx_total
    integer, intent(in) :: ny_total
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
  • private pure subroutine fold_north_centre_3d(fld, nx_total, ny_total, nz, nx_phys, ny_phys, nghost)

    3D T-fold halo-fill — identical per level.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: fld(nx_total,ny_total,nz)

    Cell-centred 3D field, shape (nx_total, ny_total, nz).

    integer, intent(in) :: nx_total
    integer, intent(in) :: ny_total
    integer, intent(in) :: nz
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost

public interface fold_north_corner

  • private pure subroutine fold_north_corner_2d(fld, nx_face, ny_face, nx_phys, ny_phys, nghost, negate)

    2D Bu-corner fold: north-halo fill + on-line projection.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: fld(nx_face,ny_face)

    Corner field, shape (nx_total+1, ny_total+1).

    integer, intent(in) :: nx_face
    integer, intent(in) :: ny_face
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
    logical, intent(in) :: negate

    .true. → negate (true-vector component); .false. → copy (scalar / pseudoscalar vorticity).

public interface fold_north_u_face

  • private pure subroutine fold_north_u_face_2d(u, nx_face, ny_total, nx_phys, ny_phys, nghost, negate)

    Fill the north halo of a 2D x-face (Cu) field. Sign-flipped by default (negate absent / .true., the true-vector contract — wind stress, velocity). negate=.false. copies instead: for a SCALAR carried on a u-face (e.g. the viscous remnant visc_rem_u — a fraction, not a flux component), the 180-degree fold rotation still swaps which side of the seam the value sits on, but the value itself does not change sign (see fold_north_corner_2d’s negate for the matching corner-stagger contract).

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: u(nx_face,ny_total)

    x-face field, shape (nx_total+1, ny_total).

    integer, intent(in) :: nx_face
    integer, intent(in) :: ny_total
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
    logical, intent(in), optional :: negate

    .true. (default) = true-vector component; .false. = scalar.

  • private pure subroutine fold_north_u_face_3d(u, nx_face, ny_total, nz, nx_phys, ny_phys, nghost, negate)

    3D x-face (Cu) north-halo fill, per-level identical. See the 2D twin for the negate (vector vs. scalar) contract.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: u(nx_face,ny_total,nz)

    x-face 3D field, shape (nx_total+1, ny_total, nz).

    integer, intent(in) :: nx_face
    integer, intent(in) :: ny_total
    integer, intent(in) :: nz
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
    logical, intent(in), optional :: negate

    .true. (default) = true-vector component; .false. = scalar.

public interface fold_north_v_face

  • private pure subroutine fold_north_v_face_2d(v, nx_total, ny_face, nx_phys, ny_phys, nghost, negate)

    2D y-face (Cv) fold: north-halo fill + on-line antisymmetric projection at the fold row. Used for the barotropic bt_vbt field in the BT fast loop. negate (default .true., see the u-face twin) selects true-vector (sign flip + self-conjugate zero) vs. scalar (copy + self-conjugate left unchanged, matching fold_north_corner_2d’s scalar contract) — a scalar on a v-face (e.g. visc_rem_v) is the SAME physical attribute of the SAME face seen from both sides of the seam, so the duplicated DOF at the fold line must agree, not cancel.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: v(nx_total,ny_face)

    y-face 2D field, shape (nx_total, ny_total+1).

    integer, intent(in) :: nx_total
    integer, intent(in) :: ny_face
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
    logical, intent(in), optional :: negate

    .true. (default) = true-vector component; .false. = scalar.

  • private pure subroutine fold_north_v_face_3d(v, nx_total, ny_face, nz, nx_phys, ny_phys, nghost, negate)

    3D y-face (Cv) fold: north-halo fill + on-line antisymmetric projection at the fold row. See the 2D twin for the negate (vector vs. scalar) contract.

    Arguments

    Type IntentOptional Attributes Name
    real(kind=wp), intent(inout) :: v(nx_total,ny_face,nz)

    y-face 3D field, shape (nx_total, ny_total+1, nz).

    integer, intent(in) :: nx_total
    integer, intent(in) :: ny_face
    integer, intent(in) :: nz
    integer, intent(in) :: nx_phys
    integer, intent(in) :: ny_phys
    integer, intent(in) :: nghost
    logical, intent(in), optional :: negate

    .true. (default) = true-vector component; .false. = scalar.


Subroutines

private pure subroutine fold_north_centre_2d(fld, nx_total, ny_total, nx_phys, ny_phys, nghost)

Fill the north halo of a 2D cell-centred field by the T-fold.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: fld(nx_total,ny_total)

Cell-centred field, shape (nx_total, ny_total).

integer, intent(in) :: nx_total
integer, intent(in) :: ny_total
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost

private pure subroutine fold_north_centre_3d(fld, nx_total, ny_total, nz, nx_phys, ny_phys, nghost)

3D T-fold halo-fill — identical per level.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: fld(nx_total,ny_total,nz)

Cell-centred 3D field, shape (nx_total, ny_total, nz).

integer, intent(in) :: nx_total
integer, intent(in) :: ny_total
integer, intent(in) :: nz
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost

private pure subroutine fold_north_corner_2d(fld, nx_face, ny_face, nx_phys, ny_phys, nghost, negate)

2D Bu-corner fold: north-halo fill + on-line projection.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: fld(nx_face,ny_face)

Corner field, shape (nx_total+1, ny_total+1).

integer, intent(in) :: nx_face
integer, intent(in) :: ny_face
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost
logical, intent(in) :: negate

.true. → negate (true-vector component); .false. → copy (scalar / pseudoscalar vorticity).

private pure subroutine fold_north_u_face_2d(u, nx_face, ny_total, nx_phys, ny_phys, nghost, negate)

Fill the north halo of a 2D x-face (Cu) field. Sign-flipped by default (negate absent / .true., the true-vector contract — wind stress, velocity). negate=.false. copies instead: for a SCALAR carried on a u-face (e.g. the viscous remnant visc_rem_u — a fraction, not a flux component), the 180-degree fold rotation still swaps which side of the seam the value sits on, but the value itself does not change sign (see fold_north_corner_2d’s negate for the matching corner-stagger contract).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: u(nx_face,ny_total)

x-face field, shape (nx_total+1, ny_total).

integer, intent(in) :: nx_face
integer, intent(in) :: ny_total
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost
logical, intent(in), optional :: negate

.true. (default) = true-vector component; .false. = scalar.

private pure subroutine fold_north_u_face_3d(u, nx_face, ny_total, nz, nx_phys, ny_phys, nghost, negate)

3D x-face (Cu) north-halo fill, per-level identical. See the 2D twin for the negate (vector vs. scalar) contract.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: u(nx_face,ny_total,nz)

x-face 3D field, shape (nx_total+1, ny_total, nz).

integer, intent(in) :: nx_face
integer, intent(in) :: ny_total
integer, intent(in) :: nz
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost
logical, intent(in), optional :: negate

.true. (default) = true-vector component; .false. = scalar.

private pure subroutine fold_north_v_face_2d(v, nx_total, ny_face, nx_phys, ny_phys, nghost, negate)

2D y-face (Cv) fold: north-halo fill + on-line antisymmetric projection at the fold row. Used for the barotropic bt_vbt field in the BT fast loop. negate (default .true., see the u-face twin) selects true-vector (sign flip + self-conjugate zero) vs. scalar (copy + self-conjugate left unchanged, matching fold_north_corner_2d’s scalar contract) — a scalar on a v-face (e.g. visc_rem_v) is the SAME physical attribute of the SAME face seen from both sides of the seam, so the duplicated DOF at the fold line must agree, not cancel.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: v(nx_total,ny_face)

y-face 2D field, shape (nx_total, ny_total+1).

integer, intent(in) :: nx_total
integer, intent(in) :: ny_face
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost
logical, intent(in), optional :: negate

.true. (default) = true-vector component; .false. = scalar.

private pure subroutine fold_north_v_face_3d(v, nx_total, ny_face, nz, nx_phys, ny_phys, nghost, negate)

3D y-face (Cv) fold: north-halo fill + on-line antisymmetric projection at the fold row. See the 2D twin for the negate (vector vs. scalar) contract.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(inout) :: v(nx_total,ny_face,nz)

y-face 3D field, shape (nx_total, ny_total+1, nz).

integer, intent(in) :: nx_total
integer, intent(in) :: ny_face
integer, intent(in) :: nz
integer, intent(in) :: nx_phys
integer, intent(in) :: ny_phys
integer, intent(in) :: nghost
logical, intent(in), optional :: negate

.true. (default) = true-vector component; .false. = scalar.