| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public | :: | beta | = | 0.0_wp |
Meridional gradient |
|
| logical, | public | :: | bound_coriolis | = | .false. |
MOM6 |
|
| integer, | public | :: | corner_h_variant | = | CORNER_H_CELL_MEAN |
PV corner-thickness construction (energy scheme).
|
|
| real(kind=wp), | public | :: | f_0 | = | 0.0_wp |
f-plane baseline. |
|
| real(kind=wp), | public, | allocatable | :: | f_corner(:,:) |
Coriolis parameter (1/s) at C-grid corners, shape (nx+1, ny+1). |
||
| logical, | public | :: | hk_pair_floor | = | .false. |
Run the |
|
| logical, | public | :: | is_init | = | .false. |
True between |
|
| type(scratch_3d_buffer_t), | public | :: | ke_centre |
Kinetic energy at cell centres for the gradient(KE) form. |
|||
| type(scratch_3d_buffer_t), | public | :: | mass_flux_u |
HK path: u_face_x * h_at_u_face (mass flux per face) at
east faces. Same shape as |
|||
| type(scratch_3d_buffer_t), | public | :: | mass_flux_v |
HK path: v_face_y * h_at_v_face at north faces. Shape
(nx, ny+1, nz). Same usage caveat as |
|||
| logical, | public | :: | no_slip | = | .false. |
Lateral boundary condition at coasts (spec §14 C1).
|
|
| integer, | public | :: | pv_adv_scheme | = | PV_ADV_CENTERED |
PV face-interpolation scheme (orthogonal to |
|
| type(scratch_3d_buffer_t), | public | :: | pv_flux_x |
du/dt at east faces. |
|||
| type(scratch_3d_buffer_t), | public | :: | pv_flux_y |
dv/dt at north faces. |
|||
| integer, | public | :: | pv_variant | = | PV_VARIANT_SADOURNY |
Active PV/Coriolis scheme variant. Defaults to Sadourny;
set to |
|
| type(scratch_3d_buffer_t), | public | :: | q_corner |
Sadourny path: relative vorticity ζ at corners. HK path: per-mass PV q = (f + ζ) / h_at_corner at corners. Both kernels write-then-read this in a single call so the repurposing is safe — they never coexist within one stage. |
|||
| logical, | public | :: | state_fluxes | = | .false. |
|
|
| logical, | public | :: | use_hk_correction | = | .false. |
Convenience flag mirroring |
|
| logical, | public | :: | weno_velocity_smooth | = | .false. |
|
Counted allocatable footprint of the Coriolis-advection slot (0 when unallocated). One arr_bytes term per array — add a term here when a new allocatable joins the type.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(in) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(inout) | :: | this |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(inout) | :: | this |
Allocate the 4 scratch buffers sized at
(nx_face / ny_face / corner, nz). Default nz=1 covers the
barotropic kernel; passing nz_ml sizes them for the
multilayer kernel. Same backward-compatible pattern as
continuity_init.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in), | optional | :: | nz_ml |
Populate f_corner with a beta-plane profile
f(y) = f_0 + beta * (y - y_ref)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(coriolis_adv_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| real(kind=wp), | intent(in) | :: | f_0 | |||
| real(kind=wp), | intent(in) | :: | beta | |||
| real(kind=wp), | intent(in) | :: | y_ref |
type :: coriolis_adv_t logical :: is_init = .false. !! True between `init` and `destroy`. Prefer this to !! `allocated(...)` — tracks GPU device attachment too. integer :: pv_variant = PV_VARIANT_SADOURNY !! Active PV/Coriolis scheme variant. Defaults to Sadourny; !! set to `PV_VARIANT_SADOURNY_HK` to engage the Arakawa-Hsu !! correction. Driven from `&ocean_setup_nml !! ocean_coriolis_form` via `parse_pv_variant`. logical :: use_hk_correction = .false. !! Convenience flag mirroring `pv_variant == SADOURNY_HK`. !! Diagnostic only — the dispatch in `ocean_dyn` reads !! `pv_variant` directly. integer :: pv_adv_scheme = PV_ADV_CENTERED !! PV face-interpolation scheme (orthogonal to `pv_variant`): !! `PV_ADV_CENTERED` (default, 2-pt corner average -> bit-identical) !! or `PV_ADV_WENO{3,5,7}` (upwind-biased WENO-Z reconstruction of the !! corner absolute vorticity onto the faces in the Sadourny path). !! Driven from `&ocean_coriolis_nml pv_adv_scheme` via !! `parse_pv_adv_scheme`; weno5/weno7 require nghost>=4/5 !! (`pv_adv_required_nghost`). logical :: weno_velocity_smooth = .false. !! `&ocean_coriolis_nml weno_velocity_smooth` (MOM6 !! `WENO_VELOCITY_SMOOTH`, default off): when on, the WENO !! smoothness indicators are computed from the tangential velocity !! rather than the vorticity. Off = vorticity-based (MOM6 default). logical :: state_fluxes = .false. !! `&ocean_coriolis_nml use_state_fluxes` — mass-consistent !! CorAdCalc. Config guarantees `form="sadourny_energy"` + !! `split_scheme="pred_corr"`; the dyn driver forwards it to !! `coriolis_adv_compute_tendencies(use_state_fluxes=)` in the !! CORRECTOR stage only (the predictor keeps the recompute — !! its continuity has not run yet this step). logical :: no_slip = .false. !! Lateral boundary condition at coasts (spec §14 C1). !! `.false.` (default) = FREE-SLIP: the corner relative !! vorticity is multiplied by `wet_q` so a land corner !! contributes zero rel-vort (tangential velocity free at the !! wall, MOM6's free-slip closure). `.true.` = NO-SLIP: !! the factor becomes `2 - wet_q` (image vorticity, MOM6's no-slip). !! Set from `&ocean_hvisc_nml no_slip` (shared with the lateral !! strain). All-wet ⇒ `wet_q≡1` ⇒ factor `≡1` ⇒ bit-identical. logical :: hk_pair_floor = .false. !! Run the `sadourny_hk` PAIR-FLOORED passes (`hk_pair_coef`) even !! with `&vcoord_nml zfixed_closed_faces` off. Latched at setup !! for the coordinates that lay STATIC bed fillers (`z_fixed`, !! `zstar`, `zstar_full`): over a stepped bed an OPEN face then !! pairs a live cell with a `zstar_h_min` filler, so an HK "cross" !! pair meets a corner of fillers (`h_corner ~ 1e-4 m`) against a !! transport through a live face — the same unbounded !! `h_face/h_corner` the floor exists for, four decades larger than !! on the closed-face partial cells it was written against. The !! floor is inactive wherever no cell outweighs the other three of !! its corner, so a flat bed stays bit-identical. Off (default) !! for every other coordinate ⇒ bit-identical there. integer :: corner_h_variant = CORNER_H_CELL_MEAN !! PV corner-thickness construction (energy scheme). !! `CORNER_H_CELL_MEAN` (default, bit-identical) — wet-area 4-cell !! mean, `CORIOLIS_H_MIN_PV`-capped. `CORNER_H_MOM6_AREA` — MOM6's !! `q = abs_vort·Area_q/(hArea_q + PV_VOL_NEGLECT)`. The two are !! algebraically identical above the floor; they differ only in the !! vanishing-thickness guard. Set from `&ocean_coriolis_nml corner_h` !! at setup (config fail-loud on non-energy forms); read host-side !! into a local flag in the kernel. logical :: bound_coriolis = .false. !! MOM6 `BOUND_CORIOLIS`. When !! `.true.` (energy scheme only — `&ocean_coriolis_nml bound_coriolis`, !! config fail-loud on any other form) the energy-scheme PV flux is !! clamped into the range of the four neighbouring `(f+ζ)·v` !! velocity-form estimates BEFORE the KE-gradient subtraction, capping !! the thin-layer `q·vh` blow-up. Read host-side into a local flag in !! the kernel; default `.false.` ⇒ untaken branch ⇒ bit-identical. ! ---- Coriolis parameter field ---- ! `f_corner` holds f at C-grid corners (SW corner of cell ! (i, j) sits at position (i-1/2, j-1/2)). Both kernels read ! it here and average to the relevant face. Shape (nx+1, ny+1). ! ! Initialised to `f_0` everywhere by `init`; switch to a ! `f = f_0 + beta * (y - y_ref)` profile via ! `coriolis_adv_set_beta_plane`. For an f-plane just leave ! `f_0` at the desired value and skip the beta call. real(wp), allocatable :: f_corner(:, :) !! Coriolis parameter (1/s) at C-grid corners, shape !! (nx+1, ny+1). real(wp) :: f_0 = 0.0_wp !! f-plane baseline. `init` fills `f_corner = f_0`; later !! re-population (`set_beta_plane`) overrides on a per- !! corner basis. real(wp) :: beta = 0.0_wp !! Meridional gradient `df/dy` (1/(s·m)). Diagnostic / !! convenience storage — the field-of-record is `f_corner`. ! ---- Per-step scratch ---- type(scratch_3d_buffer_t) :: q_corner !! Sadourny path: relative vorticity ζ at corners. !! HK path: per-mass PV q = (f + ζ) / h_at_corner at corners. !! Both kernels write-then-read this in a single call so the !! repurposing is safe — they never coexist within one stage. type(scratch_3d_buffer_t) :: ke_centre !! Kinetic energy at cell centres for the gradient(KE) form. type(scratch_3d_buffer_t) :: pv_flux_x !! du/dt at east faces. type(scratch_3d_buffer_t) :: pv_flux_y !! dv/dt at north faces. type(scratch_3d_buffer_t) :: mass_flux_u !! HK path: u_face_x * h_at_u_face (mass flux per face) at !! east faces. Same shape as `pv_flux_x` — (nx+1, ny, nz). !! Unused by the Sadourny path; allocated regardless so the !! lifecycle is uniform. type(scratch_3d_buffer_t) :: mass_flux_v !! HK path: v_face_y * h_at_v_face at north faces. Shape !! (nx, ny+1, nz). Same usage caveat as `mass_flux_u`. contains procedure, non_overridable :: init => coriolis_adv_init procedure, non_overridable :: destroy => coriolis_adv_destroy procedure, non_overridable :: enter_data => coriolis_adv_enter_data procedure, non_overridable :: exit_data => coriolis_adv_exit_data procedure, non_overridable :: set_beta_plane => coriolis_adv_set_beta_plane procedure, non_overridable :: bytes => coriolis_adv_bytes end type coriolis_adv_t