Type taxonomy + per-edge BC config + the composed slot on ocean_state_t.
Six BC types implemented end-to-end (WALL, OPEN, TIDAL, CLAMPED, SPONGE,
CHAPMAN); INFLOW/DISCHARGE/NESTED tags are declared for cross-backend
alignment but error stop if encountered. Per-edge granularity: each of
the four outer edges carries one ocean_bc_face_tag_t, read independently
by the dispatch helpers in rdb_ocean_boundary.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public, | parameter | :: | OBC_CHAPMAN | = | 9 |
Orlanski radiation on η with implicit phase-speed estimation. Uses
persistent |
| integer, | public, | parameter | :: | OBC_CLAMPED | = | 7 |
Hard Dirichlet on η + u + v + per-tracer values, sourced from |
| integer, | public, | parameter | :: | OBC_DISCHARGE | = | 6 |
Prescribed volume flux. Cross-backend symmetry only. |
| integer, | public, | parameter | :: | OBC_INFLOW | = | 5 |
Prescribed normal velocity + tracer. Cross-backend symmetry only. |
| integer, | public, | parameter | :: | OBC_INVALID | = | -1 |
Sentinel returned by |
| integer, | public, | parameter | :: | OBC_MAX_TIDAL_CONSTITUENTS | = | 8 | |
| integer, | public, | parameter | :: | OBC_NESTED | = | 4 |
Two-way nesting (not yet implemented). Behaves like OPEN to kernels. |
| integer, | public, | parameter | :: | OBC_OPEN | = | 2 |
Flather radiation — gravity-wave outflow + η clamped to a reference
(zero by default, supplied via |
| integer, | public, | parameter | :: | OBC_PERIODIC | = | 10 |
Ghost-wrap periodic boundary: ghost columns/rows hold copies of the
opposite interior so kernels see a seamless domain. Requires
|
| integer, | public, | parameter | :: | OBC_SPONGE | = | 8 |
Relaxation band — BC kernel falls through to WALL at the outer face;
the sponge kernel relaxes the interior band toward |
| integer, | public, | parameter | :: | OBC_TIDAL | = | 3 |
Prescribed multi-constituent η; composed into |
| real(kind=wp), | public, | parameter | :: | OBC_TIDE_MATCH_TOL | = | 1.0e-4_wp |
Relative tolerance for matching an OBC edge constituent’s angular
frequency to a catalog entry ( |
| integer, | public, | parameter | :: | OBC_TRIPOLAR_FOLD | = | 11 |
Tripolar north-fold seam (Murray 1996). NORTH edge only. The fold
exchange ( |
| integer, | public, | parameter | :: | OBC_WALL | = | 1 |
Closed wall (hard-zero). Default for every edge. |
Configuration for one outer edge. Defaults yield a closed wall.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public | :: | bc_type | = | OBC_WALL | ||
| real(kind=wp), | public | :: | clamped_eta | = | 0.0_wp | ||
| real(kind=wp), | public, | allocatable | :: | clamped_tracer(:) |
Per-tracer Dirichlet values for CLAMPED inflow. Size
|
||
| real(kind=wp), | public | :: | clamped_u | = | 0.0_wp | ||
| real(kind=wp), | public | :: | clamped_v | = | 0.0_wp | ||
| integer, | public | :: | n_tidal_constituents | = | 0 | ||
| logical, | public | :: | sponge_relax_tracers | = | .false. |
When .true. the legacy band sponge relaxes tracer |
|
| real(kind=wp), | public | :: | sponge_strength | = | 0.0_wp | ||
| integer, | public | :: | sponge_width | = | 0 | ||
| real(kind=wp), | public | :: | tidal_amp(OBC_MAX_TIDAL_CONSTITUENTS) | = | 0.0_wp | ||
| real(kind=wp), | public | :: | tidal_arg(OBC_MAX_TIDAL_CONSTITUENTS) | = | 0.0_wp |
Equilibrium + nodal phase |
|
| real(kind=wp), | public | :: | tidal_fnodal(OBC_MAX_TIDAL_CONSTITUENTS) | = | 1.0_wp |
18.6-yr nodal amplitude factor |
|
| real(kind=wp), | public | :: | tidal_omega(OBC_MAX_TIDAL_CONSTITUENTS) | = | 0.0_wp | ||
| real(kind=wp), | public | :: | tidal_phase(OBC_MAX_TIDAL_CONSTITUENTS) | = | 0.0_wp |
Per-state OBC bookkeeping. Composed onto ocean_state_t; the
dispatch helpers in rdb_ocean_boundary consume it via class(*)
polymorphism, keeping kernels decoupled from the full state.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | public, | allocatable | :: | data_eta_east(:) | |||
| real(kind=wp), | public, | allocatable | :: | data_eta_north(:) | |||
| real(kind=wp), | public, | allocatable | :: | data_eta_south(:) | |||
| real(kind=wp), | public, | allocatable | :: | data_eta_west(:) | |||
| real(kind=wp), | public, | allocatable | :: | data_tracer_east(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | data_tracer_north(:,:,:) |
(ny|nx, nz_ml, n_tracers). |
||
| real(kind=wp), | public, | allocatable | :: | data_tracer_south(:,:,:) |
(ny|nx, nz_ml, n_tracers). |
||
| real(kind=wp), | public, | allocatable | :: | data_tracer_west(:,:,:) | |||
| real(kind=wp), | public, | allocatable | :: | data_u_east(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | data_u_west(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | data_v_north(:,:) | |||
| real(kind=wp), | public, | allocatable | :: | data_v_south(:,:) | |||
| type(ocean_bc_face_tag_t), | public | :: | east | ||||
| real(kind=wp), | public | :: | eta_old_chapman_e | = | 0.0_wp | ||
| real(kind=wp), | public | :: | eta_old_chapman_n | = | 0.0_wp | ||
| real(kind=wp), | public | :: | eta_old_chapman_s | = | 0.0_wp | ||
| real(kind=wp), | public | :: | eta_old_chapman_w | = | 0.0_wp | ||
| real(kind=wp), | public, | allocatable | :: | eta_old_east(:) | |||
| real(kind=wp), | public, | allocatable | :: | eta_old_north(:) | |||
| real(kind=wp), | public, | allocatable | :: | eta_old_south(:) | |||
| real(kind=wp), | public, | allocatable | :: | eta_old_west(:) | |||
| real(kind=wp), | public | :: | ext_u_east | = | 0.0_wp |
Exterior barotropic u, east (m/s). |
|
| real(kind=wp), | public | :: | ext_u_west | = | 0.0_wp |
Exterior barotropic u, west (m/s). |
|
| real(kind=wp), | public | :: | ext_v_north | = | 0.0_wp |
Exterior barotropic v, north (m/s). |
|
| real(kind=wp), | public | :: | ext_v_south | = | 0.0_wp |
Exterior barotropic v, south (m/s). |
|
| logical, | public | :: | has_east | = | .true. |
False when the east edge of this subdomain is an MPI seam; true when it is a physical domain edge. (analogous to has_west) |
|
| logical, | public | :: | has_north | = | .true. |
False when the north edge of this subdomain is an MPI seam; true when it is a physical domain edge. (analogous to has_west) |
|
| logical, | public | :: | has_south | = | .true. |
False when the south edge of this subdomain is an MPI seam; true when it is a physical domain edge. (analogous to has_west) |
|
| logical, | public | :: | has_west | = | .true. |
False when the west edge of this subdomain is an MPI seam (a neighbouring rank owns the cells beyond it), true when it is a physical domain edge. Set from decomp%has_west at BC configure. Default .true. => single-rank / physical-edge behaviour (bit-identical to the pre-decomp code). |
|
| logical, | public | :: | is_init | = | .false. | ||
| integer, | public | :: | n_tracers | = | 0 | ||
| integer, | public | :: | nghost | = | 0 | ||
| type(ocean_bc_face_tag_t), | public | :: | north | ||||
| logical, | public | :: | north_fold | = | .false. |
True when THIS RANK applies the tripolar north fold: the north
edge is OBC_TRIPOLAR_FOLD AND this subdomain owns the physical
north edge ( |
|
| real(kind=wp), | public | :: | nudge_tau_in | = | 0.0_wp |
Inflow nudging timescale (s, Marchesiello et al. 2001). 0 = off. |
|
| real(kind=wp), | public | :: | nudge_tau_out | = | 0.0_wp |
Outflow nudging timescale (s). 0 = off. |
|
| integer, | public | :: | nx_phys | = | 0 | ||
| integer, | public | :: | nx_total | = | 0 | ||
| integer, | public | :: | ny_phys | = | 0 | ||
| integer, | public | :: | ny_total | = | 0 | ||
| integer, | public | :: | nz_ml | = | 0 | ||
| real(kind=wp), | public | :: | orlanski_gamma | = | 1.0_wp |
Running-mean weight. 1.0 = no running mean (instant rx). |
|
| real(kind=wp), | public | :: | orlanski_rx_max | = | 10.0_wp |
Upper clamp on the nondimensional phase speed (Orlanski 1976). |
|
| logical, | public | :: | periodic_x | = | .false. |
True when west and east edges are both OBC_PERIODIC. |
|
| logical, | public | :: | periodic_y | = | .false. |
True when south and north edges are both OBC_PERIODIC. |
|
| integer, | public | :: | radiation_scheme | = | 0 |
0 = anomaly (default); 1 = orlanski. |
|
| real(kind=wp), | public | :: | res_lscale_in | = | 0.0_wp |
Inflow reservoir length scale (m). 0 ⇒ instantaneous inflow. |
|
| real(kind=wp), | public | :: | res_lscale_out | = | 0.0_wp |
Outflow reservoir length scale (m). 0 ⇒ instantaneous outflow. |
|
| real(kind=wp), | public, | allocatable | :: | rx_east(:,:) |
Running-mean rx, east edge. |
||
| real(kind=wp), | public, | allocatable | :: | rx_north(:,:) |
Running-mean rx, north edge. |
||
| real(kind=wp), | public, | allocatable | :: | rx_south(:,:) |
Running-mean rx, south edge. |
||
| real(kind=wp), | public, | allocatable | :: | rx_west(:,:) |
Running-mean rx, west edge. |
||
| type(ocean_bc_face_tag_t), | public | :: | south | ||||
| logical, | public | :: | tidal_nodal | = | .false. |
Global switch (capability C3): apply the 18.6-yr nodal factor |
|
| real(kind=wp), | public, | allocatable | :: | tres_east(:,:,:) |
East reservoir concentration |
||
| real(kind=wp), | public, | allocatable | :: | tres_north(:,:,:) |
North reservoir concentration |
||
| real(kind=wp), | public, | allocatable | :: | tres_south(:,:,:) |
South reservoir concentration |
||
| real(kind=wp), | public, | allocatable | :: | tres_west(:,:,:) |
West reservoir concentration |
||
| real(kind=wp), | public, | allocatable | :: | u_prev_east(:,:) |
Prev-call u at first interior face, east. |
||
| real(kind=wp), | public, | allocatable | :: | u_prev_north(:,:) |
Prev-call v at first interior face, north. |
||
| real(kind=wp), | public, | allocatable | :: | u_prev_south(:,:) |
Prev-call v at first interior face, south. |
||
| real(kind=wp), | public, | allocatable | :: | u_prev_west(:,:) |
Prev-call u at first interior face, west. |
||
| logical, | public | :: | use_full_flather | = | .false. |
.false. = legacy (default, bit-identical); .true. = full Flather (Flather 1976 half-characteristic form with exterior velocity). |
|
| type(ocean_bc_face_tag_t), | public | :: | west |
| procedure, public, non_overridable :: bytes => ocean_bc_state_bytes |
Resolve an OBC edge constituent’s angular frequency omega (rad/s)
to the tide catalog index (rdb_ocean_tide_astro::TIDE_OMEGA) whose
frequency matches within the relative tolerance OBC_TIDE_MATCH_TOL.
Returns 0 when no catalog entry is within tolerance (unknown
constituent) or when omega <= 0 — the caller (OBC setup) converts a
0 to a fail-loud error stop, keeping this function pure.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | omega |
The tag an edge’s OUTER FACE behaves as for the no-normal-flow
closures (mass-flux zeroing in the continuity, the uhbt/vhbt
wall reconciliation, the lateral tracer-diffusion walls).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | bc_type |
Raw per-edge tag ( |
Convert a config-namelist edge string → integer OBC tag.
Case-INSENSITIVE (to_lower), so “OPEN”/”Open”/”open” all parse
to OBC_OPEN. An unrecognised name returns OBC_INVALID
(PR-6 fail-loud): a typo must NOT silently close the boundary to
a wall. validate_config rejects OBC_INVALID (naming the
edge) before configure_ocean_bc consumes any parse result, so
no production caller ever sees the sentinel at a live edge.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | name |
Counted allocatable footprint of the boundary state slot (0 when unallocated).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ocean_bc_state_t), | intent(in) | :: | this |
Bake the nodal/astronomical correction into one edge’s per-constituent
tidal_fnodal / tidal_arg. For each of face%n_tidal_constituents,
resolve the constituent by frequency (obc_match_constituent) and set
tidal_fnodal(nc) = f_all(ic), tidal_arg(nc) = v_all(ic) + u_all(ic).
f_all / u_all come from nodal_fu, v_all from
equilibrium_arguments, all sized TIDES_CATALOG_SIZE. On an
unmatched constituent it leaves that entry untouched and returns
ierr = nc (the 1-based edge slot that failed) so the caller can fail
loud; ierr = 0 on success. pure — no logging / no error stop.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_face_tag_t), | intent(inout) | :: | face | |||
| real(kind=wp), | intent(in) | :: | f_all(TIDES_CATALOG_SIZE) | |||
| real(kind=wp), | intent(in) | :: | u_all(TIDES_CATALOG_SIZE) | |||
| real(kind=wp), | intent(in) | :: | v_all(TIDES_CATALOG_SIZE) | |||
| integer, | intent(out) | :: | ierr |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this |
GPU mapping for ocean_bc_state_t.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this |
GPU unmapping — components first, parent last (reverse of enter_data).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this |
Cache grid extents and derive periodic flags. Data buffers stay
unallocated until a data source asks for them. Call
ocean_bc_validate_periodic after setting per-edge tags if any edge
is OBC_PERIODIC; init itself only derives the convenience flags.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this | |||
| type(hgrid_t), | intent(in) | :: | grid | |||
| integer, | intent(in) | :: | nz_ml | |||
| integer, | intent(in), | optional | :: | n_tracers |
Set the physical-domain-edge flags from a decomposition descriptor.
Called once by the driver after configure_ocean_bc so kernels can
gate wall / BC / periodic closures on physical edges (a subdomain
seam is never a wall), and re-derives the rank-local north_fold
(the fold is applied only by the rank that owns the north edge).
Default .true. keeps single-rank bit-identity.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this | |||
| logical, | intent(in) | :: | has_west |
True when the west edge is a physical domain edge, false at an MPI seam. |
||
| logical, | intent(in) | :: | has_east |
True when the east edge is a physical domain edge, false at an MPI seam. |
||
| logical, | intent(in) | :: | has_south |
True when the south edge is a physical domain edge, false at an MPI seam. |
||
| logical, | intent(in) | :: | has_north |
True when the north edge is a physical domain edge, false at an MPI seam. |
Pre-create GRID TOPOLOGY injection (Python runtime API plan,
P2.5): force per-dimension periodicity the Oceananigans way
(docs/ocean_python_api_plan.md S5b) — “the grid owns
periodicity”, not the per-edge &ocean_bc_nml tags. Sets
periodic_x/periodic_y directly and back-fills the edge tags
on every axis the caller marks periodic (both edges together, so
a west/east — or south/north — mismatch is structurally
unrepresentable through this entry point, unlike the namelist
path which needs ocean_bc_validate_periodic to catch one). An
axis the caller does NOT mark periodic is left untouched: its
edge tags keep whatever physical BC configure_ocean_bc already
derived from &ocean_bc_nml — periodicity is a GRID property,
but the wall/open/clamped/… physics for a Bounded dimension
stays the namelist’s job.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this | |||
| logical, | intent(in) | :: | periodic_x | |||
| logical, | intent(in) | :: | periodic_y | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero ( |
Validate the tripolar north-fold tag. Call after all per-edge
tags are set and after ocean_bc_state_init. Refreshes
north_fold and stops with a diagnostic if any rule fails.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a tripolar-fold configuration violation when
present; absent behaves as today ( |
Validate periodic pairing + ghost-width + sponge incompatibility.
Call after all per-edge tags are set and after ocean_bc_state_init.
Derives periodic_x / periodic_y from the final tags and
stops with a diagnostic message if any rule is violated.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(ocean_bc_state_t), | intent(inout) | :: | this | |||
| integer, | intent(out), | optional | :: | ierr |
Non-zero on a periodic-BC pairing/ghost-width violation when
present; absent behaves as today ( |