Appearance
adam_forest_object
ADAM, forest class definition — orchestrator of a forest of realms.
The forest tends an array of realms (realm_object extensions, e.g. prism_cpu_object, prism_fnl_object). It is a behavior-only class: it owns no derived-type state. Each realm lives in the program driver as a concrete monomorphic array (type(prism_cpu_object), target :: realm(N)); the driver points an array of realm_pointer at its elements and the forest receives that, type(realm_pointer), intent(inout) :: realm(:) (element is is realm(is)%ptr). It never receives a polymorphic array class(realm_object) :: realm(:): nvfortran miscompiles the indexing of one (issue #96). The forest orchestrates inter-realm operations:
- sequence per-realm initialize / finalize calls
- reduce per-realm dt to a global dt (min reduction)
- iterate per-realm timestep advance
- iterate per-realm post-step diagnostics / IO
- reduce per-realm termination predicate to a global done (AND reduction)
The forest NEVER reaches inside a realm's private state; it only invokes the realm-side TBPs that carry the _forest suffix. Together these TBPs form the orchestrator contract (see adam_realm_object).
Class-with-TBPs (not module-of-routines) so future forest-level configuration (MPI sub-communicator topology, inter-realm connectivity descriptor) can be added as intrinsic-typed state without a module API break.
See docs/concepts/forest.md for the conceptual overview of the multi-realm machinery (manifest schema, α/β cadence trade-offs, phase cycle) and src/lib/common/README.md → "Forest orchestration" for the library-developer contract surface.
Source: src/lib/common/adam_forest_object.F90
Dependencies
Contents
- forest_object
- seam_rows_t
- seam_register_face_t
- initialize
- initialize_from_manifest
- finalize
- compute_global_dt
- evolve_one_step
- is_done
- post_step
- regrid
- rebuild_topology_timed
- regrid_realms
- balance_seam_marks
- balance_mixed_pair
- side_scan
- side_set
- clear_tree_marks
- check_marks_agree
- fill_all_seams
- simulate
- simulate_from_manifest
- start_timing
- report_timing
- check_beta_admissibility
- populate_inter_realm_topology
- check_couplings
- resolve_auto_couplings
- seam_sides
- check_nested
- leaf_peers
- check_mixed_seam
- build_seam_rows
- enumerate_seam_side
- store_seam_rows
- group_rows
- realm_face_leaves
- push_row
- leaf_metrics
- ghost_slab_extents
- wrap_periodic_tangential
- register_intra_realm_amr_seams
- apply_reflux_corrections
- share_flux_register
- seam_leaf_codes
- cell_ratio_log2
- tree_marks_text
- tree_has_marks
- seam_cell_size
- is_2to1_piece
- pair_refine_ratio
- seam_register_faces
- size_pairs
- leaf_on_realm_face
- inside_domain
- ghost_label
Derived Types
forest_object
Behavior-only orchestrator of an array of realms.
Components
| Name | Type | Attributes | Description |
|---|---|---|---|
n | integer(kind=I4P) | Number of realms in the forest (set by initialize from size(realm)). | |
flux_register | type(flux_register_object) | Coarse-fine interface reflux machinery. | |
timing | logical | ||
wtime | real(kind=R8P) | ||
rebuilds | integer(kind=I4P) | ||
manifest | type(forest_manifest_t) | ||
has_manifest | logical | ||
rebuild_topology | logical |
Type-Bound Procedures
| Name | Attributes | Description |
|---|---|---|
initialize | pass(self) | Sequence each realm's initialize_forest at startup (single shared INI). |
initialize_from_manifest | pass(self) | Like initialize, but each realm reads its own INI from a forest manifest. |
finalize | pass(self) | Sequence each realm's finalize_forest at shutdown. |
compute_global_dt | pass(self) | Min-reduce each realm's compute_local_dt_forest across the forest. |
evolve_one_step | pass(self) | Iterate realm(😃%advance_one_step_forest(dt) for one global timestep. |
is_done | pass(self) | AND-reduce each realm's is_done_forest across the forest. |
post_step | pass(self) | Iterate realm(😃%post_step_forest for the per-step diagnostics/IO block. |
regrid | pass(self) | Iterate realm(😃%regrid_forest, rebuild the topology on a change. |
simulate | pass(self) | Main entry point (single shared INI): drive the full simulation. |
simulate_from_manifest | pass(self) | Main entry point (per-realm INIs via forest manifest). |
populate_inter_realm_topology | pass(self) | Translate manifest face-pairs into maps of neighbors. |
register_intra_realm_amr_seams | pass(self) | Register intra-realm AMR coarse-fine faces in the flux |
apply_reflux_corrections | pass(self) | Apply Berger-Colella reflux to coarse-side. |
share_flux_register | pass(self) | Copy the register into every realm (#68 A2). |
fill_all_seams | pass(self) | Fill every seam on committed q (issue #110). |
regrid_realms | pass(self) | The phased multi-realm regrid (issue #110). |
rebuild_topology_timed | pass(self) | Rebuild the topology, refill the seams (#110). |
balance_seam_marks | pass(self) | Balance the marks across the seams (#110). |
start_timing | pass(self) | Arm the timing report (issue #53). |
report_timing | pass(self) | Print the timing report (issue #53). |
seam_rows_t
Growable list of integer rows, used while the seam rows are enumerated.
Components
| Name | Type | Attributes | Description |
|---|---|---|---|
row | integer(kind=I4P) | allocatable | Rows (n, columns). |
n | integer(kind=I4P) | Rows in use. |
seam_register_face_t
One inter-realm register face (issue #110 P3, seam_register_faces): its coarse and fine sides and the coarse leaf.
Components
| Name | Type | Attributes | Description |
|---|---|---|---|
rc | integer(kind=I4P) | Coarse-side realm. | |
fc | integer(kind=I4P) | Coarse-side face (FACE_* code). | |
rf | integer(kind=I4P) | Fine-side realm. | |
ff | integer(kind=I4P) | Fine-side face (FACE_* code). | |
code_c | integer(kind=I8P) | The coarse seam leaf. | |
refined | logical | A 2:1 face (else equal cells, realm_a coarse by convention). |
Subroutines
initialize
Initialize the forest and every realm it tends.
fortran
subroutine initialize(self, realm, filename)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms to initialize. | |
filename | character(len=*) | in | Input parameters file name (shared across realms for v1). |
Call graph
initialize_from_manifest
Initialize the forest and every realm using per-realm INIs from a manifest.
Like initialize but each realm receives its OWN INI path (manifest%realm_ini(is)) instead of a shared filename. After all realms are initialized, translates the manifest's face-pair list into per-realm maps%inter_realm_neighbors entries.
The driver MUST allocate manifest%realms_number realms of the concrete app type and point realm(:) at them before calling this — the forest does not allocate the realms (it cannot, since realm_object is abstract and each app has its own extension). Environment value. Environment status. MPI error.
fortran
subroutine initialize_from_manifest(self, realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms to initialize. | |
manifest | type(forest_manifest_t) | in | Parsed manifest (per-realm INI paths + topology). |
Call graph
finalize
Shut down the forest and every realm it tends.
Iterates realm(is)%finalize_forest in increasing index order; each realm closes its IO files, releases its resources, and finalizes its MPI handler.
fortran
subroutine finalize(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest. | |
realm | type(realm_pointer) | inout | The realms to shut down. |
Call graph
compute_global_dt
Compute the forest-global stability-limited dt.
Each realm reports its local dt via compute_local_dt_forest; the forest takes the min across all realms (intra-process) and then across all MPI ranks (MPI_ALLREDUCE on MPI_COMM_WORLD). Returns the bit-identical global min every rank should advance by.
fortran
subroutine compute_global_dt(self, realm, dt)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest. | |
realm | type(realm_pointer) | inout | The realms to query. | |
dt | real(kind=R8P) | out | Global stability-limited dt. |
Call graph
evolve_one_step
Advance every realm by one global timestep — α end-of-step barrier semantics.
N=1 fast path: realm owns the whole step (advance_one_step_forest). No seam machinery is exercised (there are no peer seams to refresh).
N>1 multi-realm path: per-seam coupling cadence (α / β).
The forest drives an integrator-agnostic K-stage clock with K_realm(is) = realm(is)%stages_per_step_forest() and K_max = max(K_realm). Asymmetric per-realm K is a first-class operating mode under α; the per-stage TBPs (begin/end_stage_forest) are gated behind k <= K_realm(is) so a realm with K < K_max no-ops the trailing stages.
Each inter-realm seam carries a coupling_cadence from the manifest (cached on the realm as seam_local_cadence(p)):
α (CADENCE_END_OF_STEP, default; AMReX-aligned coarse-fine convention) Mid-step peer ghosts are INTENTIONALLY FROZEN AT t^n. Phase 0 (below) fills the seam ghosts of every realm's committed q from the peers' committed q, once per step before open_step_forest, and each realm's open_step_forest copies them into every stage buffer, so stages 1..K all read the peer state at the start of the step. This is structurally identical to AMReX's FillCoarsePatch reading coarse t^n data during fine sub-steps (Berger-Oliger 1984; AMReX_Amr.cpp::timeStep). α admits asymmetric per-realm K (the K-equality guard is removed). Cost: first-order seam coupling in time (issue #113: before it the stages read seam ghosts no fill reached).
β (CADENCE_STAGE_COINCIDENT, opt-in) Peer ghosts are refreshed once per RK substage, inside the K loop (Phase 2 below), before end_stage_forest reads them. Admissible only when both endpoint realms agree on (scheme_time, rk_scheme, nv, K) — enforced at forest init by check_beta_admissibility. Recovers bit-equivalence to a monolithic single-realm run on the union grid when admissible. Seam coupling order matches the per-realm interior order. Spatial operator MAY differ per realm.
Per-seam selection: the same forest may carry α seams and β seams simultaneously. Phase 2 iterates seams and fires only for β; Phase 0 iterates seams and fires only for α. An α seam is filled once per step; a β seam once per substage (Phase 2 fires K times).
Reflux cadence (α.r1):
The flux register's third axis is collapsed to 1. PRISM realms gate apply_reflux_to_stage_forest and accumulate_seam_fluxes_fv on the realm's own final RK substage (stage == rk%nrk). Earlier substages no-op. The mid-step apply_reflux_corrections call below therefore fires for every k, but only the k == K_realm(is) invocation does real work on realm is. Independent of α/β: β does not restore Wang 2018 per-stage RK-weighted reflux (deferred).
Phase outline:
Phase 0 — fill_seam_from_peer_forest (per-seam, α-gated), then open_step_forest (per-realm prologue: the stages start from q, the α seam ghosts included) For k = 1..K_max: Phase 1 — begin_stage_forest (per-realm, gated by k <= K_realm(is)) Phase 2 — fill_seam_from_peer_forest (per-seam, β-gated) Phase 3 — end_stage_forest (per-realm, gated by k <= K_realm(is)) + reduce_fine_sums + apply_reflux_corrections (reflux body is α.r1 end-of-step gated inside the realm) Phase 4 — close_step_forest (per-realm epilogue)
LOAD-BEARING INVARIANT (β): Phase 2 must complete on ALL realms before Phase 3 starts on ANY realm. The orchestrator's serial inner loops within a rank give this for free under the Phase-A replicated-forest layout. If a future refactor interleaves Phase 2 and Phase 3, the read-after-overwrite race returns.
Future per-realm-dt subcycling (Berger-Colella "case 4") and γ (dense-output peer reads) are deferred. β with asymmetric K would require γ-class interpolation; not in scope.
fortran
subroutine evolve_one_step(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | target | The realms to advance. |
Call graph
is_done
Decide whether the whole forest has finished evolving.
Each realm reports its local predicate via is_done_forest; the forest AND-reduces across all realms (intra-process) and then across all MPI ranks (MPI_ALLREDUCE on MPI_COMM_WORLD). AND-reduction means the forest keeps evolving as long as ANY realm wants to — matching the legacy single-realm semantics for v1 (with one realm the global predicate equals that realm's local one).
fortran
subroutine is_done(self, realm, done)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest. | |
realm | type(realm_pointer) | inout | The realms to query. | |
done | logical | out | Forest-global termination predicate. |
Call graph
post_step
Run every realm's post-step diagnostics / IO / AMR block.
fortran
subroutine post_step(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest. | |
realm | type(realm_pointer) | inout | The realms to query. |
Call graph
regrid
Let every realm regrid if its cadence asks for it now, then rebuild what the forest owns (issue #74, M5).
Runs after the step closes and before post_step, on committed q (no stage active): the fields, histories and restart files post_step saves then describe the grid the next step runs on, so a run restarted at a regrid step continues exactly as the uninterrupted one (saved before the regrid, the restart held the old grid and the restarted run diverged from the regrid step on). A realm that regrids changes its tree, so the intra-realm 2:1 faces of the flux register (and the per-block register index the positivity seam sync and the div(B) seam band read) describe the old grid: the register is rebuilt from the new trees. The fused fast path is chosen per step from flux_register%nfaces, so a run that gains or loses 2:1 faces switches path with the rebuilt register.
On a multi-realm forest (issue #110) the whole inter-realm topology depends on the block layout too: the register faces of the seams, the seam ghost rows (local, MPI send and receive), the BC_SEAM rows of the boundary crown and their device copies. After any realm regridded, populate_inter_realm_topology rebuilds all of it from the manifest kept at initialisation (it is idempotent: every structure it builds is deallocated first), then every seam is filled from its peer on the committed state, both cadences: a new seam block has no seam ghost yet, and an end-of-step seam would otherwise enter the next step with the ghosts of the old layout. Before the realms mark, the seams are filled too, so markers that read ghosts (gradient, Löhner) see the peer realm across a seam. Both fills run only when a realm regrids at runtime (or under the rebuild hook): a checkpoint holds the ghost cells, so a run without runtime AMR must not see an extra fill.
fortran
subroutine regrid(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. |
Call graph
rebuild_topology_timed
Rebuild the inter-realm topology from the kept manifest and refill every seam from its peer, timing both when ADAM_SEAM_TIMING=1 (issue #110 P6).
fortran
subroutine rebuild_topology_timed(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. |
Call graph
regrid_realms
The regrid of a multi-realm forest (issue #110): every realm marks, the forest balances the marks across the seams, every realm adapts; sweep after sweep, until no realm marks or no tree changes.
regrid_forest marks and adapts a realm in one call, so the realm adapting first could not see its peers' marks. Here each sweep runs the realm phases one realm after the other: regrid_mark_forest (the marks gathered on the replicated tree; a realm that does not mark has its tree marks cleared), balance_seam_marks (on the replicated trees, identical on every rank), then regrid_apply_forest for every realm whose tree carries a mark, a realm a peer forces to refine included. After a sweep that changed a tree the inter-realm topology is rebuilt and the seams refilled, so the next sweep marks, and the next step runs, on the new grid (rebuilt).
fortran
subroutine regrid_realms(self, realm, any_regridded, rebuilt)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. | |
any_regridded | logical | out | Some realm's tree changed. | |
rebuilt | logical | out | The topology was rebuilt after the last change. |
Call graph
balance_seam_marks
Balance the marks of the realms across their seams, on the replicated trees (issue #110).
Each realm's 2:1 sanitize first, then, seam by seam:
- one level per seam side: a refine vote on a leaf along the seam refines the whole side; the side derefines only when every leaf along it agrees, otherwise its derefine votes are dropped (the seams join one cell size per side);
- the levels across the seam: equal for
coupling = mirror, the declared 2:1 jump forrefined, at most one level apart forauto; a side below what the rule asks is raised (its derefinement dropped, or refined if below[amr] max_level), else the refinement of the side above is dropped. Repeated withsanitizeuntil nothing changes: the trees are replicated, so every rank reaches the same marks.
A coupling = auto pair is balanced face by face instead (issue #110 P3, balance_mixed_pair): each seam leaf against the leaves of the peer realm facing it, their predicted cells equal or in a ratio of 2, so the levels may differ along the seam as they do inside a realm.
fortran
subroutine balance_seam_marks(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. |
Call graph
balance_mixed_pair
Balance a coupling = auto seam face by face (issue #110 P3): for every seam leaf of realm_a and every seam leaf of realm_b next to it (their seam faces overlap or touch at an edge or a corner, also across a tangential axis periodic on both realms: the seam slab's edge and corner ghosts read those cells too), their predicted cells (a refine mark halves a leaf's cells, a derefine mark doubles them) must be equal or in a ratio of 2. The coarser of a pair too far apart is raised (its derefinement dropped, or refined below its [amr] max_level), else the finer is lowered (its refinement dropped); the caller repeats with each realm's sanitize until nothing changes. The overlaps are those of the current leaves: a derefinement is a family's, and the family's other leaves on the seam are checked too.
fortran
subroutine balance_mixed_pair(realm_a, face_a, realm_b, face_b, f, changed)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm_a | class(realm_object) | inout | Realms of the pair. | |
face_a | integer(kind=I4P) | in | Seam faces. | |
realm_b | class(realm_object) | inout | Realms of the pair. | |
face_b | integer(kind=I4P) | in | Seam faces. | |
f | integer(kind=I4P) | in | Face pair (for the message). | |
changed | logical | inout | Some mark changed. |
Call graph
side_scan
Scan the leaves of a realm along a seam face: their level (one level, error_stop otherwise) and their marks.
fortran
subroutine side_scan(this_realm, face, level, any_refine, all_deref)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | inout | Realm. | |
face | integer(kind=I4P) | in | Seam face (FACE_* code). | |
level | integer(kind=I4P) | out | Level of the leaves along the face. | |
any_refine | logical | out | Some leaf refines. | |
all_deref | logical | out | Every leaf derefines. |
Call graph
side_set
Give every leaf of a realm along a seam face the mark mark; changed if any leaf had another.
fortran
subroutine side_set(this_realm, face, mark, changed)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | inout | Realm. | |
face | integer(kind=I4P) | in | Seam face (FACE_* code). | |
mark | integer(kind=I4P) | in | TO_BE_REFINED, TO_NOT_TOUCH or TO_BE_DEREFINED. | |
changed | logical | inout | Some mark changed. |
Call graph
clear_tree_marks
Clear every mark of a replicated tree (a realm that does not mark in a sweep, issue #110).
fortran
subroutine clear_tree_marks(tree)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
tree | type(tree_object) | inout | Tree. |
Call graph
check_marks_agree
Stop if the ranks reached different marks (issue #110): every rank balances its own copy of the replicated trees, so a rank that disagreed would adapt another tree than its peers, silently, and the next exchange would deadlock or mix grids. One checksum per realm, its smallest and largest over the ranks compared.
fortran
subroutine check_marks_agree(realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | in | The realms. |
Call graph
fill_all_seams
Fill every inter-realm seam from its peer on the committed state, whatever its cadence (issue #110: around a regrid). The fills read the peer's committed q, since no stage is active between steps.
fortran
subroutine fill_all_seams(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. |
Call graph
simulate
Drive the full simulation: initialize, time-loop, finalize.
Top-level entry point the program driver calls. The time loop is: initialize → loop {evolve_one_step → post_step → is_done} → finalize. Each step invokes the orchestrator-contract TBPs on every realm; the per-realm body decides what app-specific work to do internally.
fortran
subroutine simulate(self, realm, filename)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms to evolve. | |
filename | character(len=*) | in | Input parameters file name. |
Call graph
simulate_from_manifest
Drive the full simulation using per-realm INIs from a manifest.
Like simulate but uses initialize_from_manifest to populate each realm from its own INI file, and (via that initialize) wires the inter-realm topology from the manifest. The time-loop body is identical to simulate.
fortran
subroutine simulate_from_manifest(self, realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms to evolve. | |
manifest | type(forest_manifest_t) | in | Parsed manifest. |
Call graph
start_timing
Arm the timing report when the environment sets ADAM_SEAM_TIMING=1 (issue #53): the forest times its loop, steps and reflux, every realm the phases of the seam fills of its ghosts; the forest also times the runtime regrid, its balance and topology rebuilds (issue #110 P6). Off by default, the output unchanged.
fortran
subroutine start_timing(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | The realms. |
Call graph
report_timing
Print the timing report (issue #53): the maximum over the ranks of the forest timers and, per realm, of the seam fill phases (local copy, buffers, pack, MPI, unpack) and of their sum; fills and rows summed over the ranks.
fortran
subroutine report_timing(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest. | |
realm | type(realm_pointer) | in | The realms. |
Call graph
check_beta_admissibility
Enforce β admissibility contract on every stage_coincident seam.
For each manifest face-pair with coupling_cadence == CADENCE_STAGE_COINCIDENT, query both endpoint realms' coupling_descriptor_forest and verify they agree on (scheme_time, rk_scheme, nv). On any mismatch error_stop with a precise diagnostic naming the offending pair and the specific descriptor field that disagrees. Per-realm K participation (stages_per_step_forest()) is verified too: under β both endpoints must report the same K (asymmetric-K is α's domain, not β's).
Runs once at initialize_from_manifest time, after every realm's initialize_forest has populated numerics, rk, physics.
fortran
subroutine check_beta_admissibility(realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | inout | The initialized realms. | |
manifest | type(forest_manifest_t) | in | Parsed manifest. |
Call graph
populate_inter_realm_topology
Translate manifest face-pairs into per-realm maps%inter_realm_neighbors.
Each manifest face-pair becomes TWO entries — one in realm_a's adam%maps%inter_realm_neighbors (looking outward toward realm_b) and one in realm_b's (looking back). Both entries carry the SAME coupling kind. Block indices are NOT resolved at this stage; the manifest declares realm-level coupling (which realm-face touches which realm-face), and the realm-side override of exchange_inter_realm_halos_forest is responsible for enumerating per-block face cells at exchange time. This keeps the manifest small and avoids encoding block layouts that depend on AMR / decomposition state not known at INI parse time.
fortran
subroutine populate_inter_realm_topology(self, realm, manifest_in)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | Initialized realms whose adam%maps gets populated. | |
manifest_in | type(forest_manifest_t) | in | Parsed manifest. |
Call graph
check_couplings
Validate the coupling of every manifest face pair against the realm geometry (issue #52); error_stop otherwise.
Walks the seam leaves of both sides on the replicated trees (the same result on every rank):
mirror: one cell size on each side's seam face, equal across the seam;refined: one cell size per side with ratio exactly 2 along the axes the trees refine and 1 along a null axis (a quadtree's z, issue #71; either side may be the coarse one), the same tree kind in both realms and a seam normal to a refined axis, equal block cell counts along the seam, the same[amr] seam_ghost_fill, and nested blocks: every fine seam leaf covers one 2:1 piece of the face of one coarse seam leaf (a quarter on an octree, a half on a quadtree), and even block cell counts along the refined axes in the fine realm;periodic,interpolate: schema-reserved, refused (before issue #52 they were accepted and run asmirror).
fortran
subroutine check_couplings(realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | inout | Forest realms. | |
manifest | type(forest_manifest_t) | in | Parsed manifest. |
Call graph
resolve_auto_couplings
Resolve every coupling = auto face pair into mirror or refined from the cell sizes of its two seam sides (issue #110): equal sizes join as a mirror seam, a ratio of 2 as a refined one. Runtime AMR may switch a seam from one kind to the other, so what refined requires whatever side is fine is checked every time: the same block cell counts along the seam, the same [amr] seam_ghost_fill and seam_restriction, even block cell counts in both realms. check_couplings then checks the resolved kind as a declared one. A side whose seam leaves hold several cell sizes (mixed levels along the seam, P3) leaves the pair auto: its kind is then decided face by face (leaf_peer_relation), checked by check_mixed_seam and registered by seam_register_faces.
fortran
subroutine resolve_auto_couplings(realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | in | Forest realms. | |
manifest | type(forest_manifest_t) | inout | Manifest, auto couplings resolved on return. |
Call graph
seam_sides
The coarse and fine sides of a face pair: for a refined seam the realm with the larger seam cells is the coarse side (issue #52), for a mirror seam realm_a by convention.
fortran
subroutine seam_sides(realm, pair, rc, fc, rf, ff, refined)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | in | Forest realms. | |
pair | type(forest_face_pair_t) | in | Face pair. | |
rc | integer(kind=I4P) | out | Coarse-side realm and face. | |
fc | integer(kind=I4P) | out | Coarse-side realm and face. | |
rf | integer(kind=I4P) | out | Fine-side realm and face. | |
ff | integer(kind=I4P) | out | Fine-side realm and face. | |
refined | logical | out | 2:1 seam. |
Call graph
check_nested
Every fine seam leaf must cover one 2:1 piece of the seam face of one coarse leaf: half its tangential extent, starting at its origin or at its midpoint, along each refined tangential axis, and the whole extent along a null one (a quadtree's z, issue #71).
fortran
subroutine check_nested(coarse, fine, face_f, r, pfx)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
coarse | class(realm_object) | inout | Coarse realm. | |
fine | class(realm_object) | inout | Fine realm. | |
face_f | integer(kind=I4P) | in | Fine seam face. | |
r | integer(kind=I4P) | in | Refinement ratio per axis (2, or 1 along a null axis). | |
pfx | character(len=*) | in | Error message prefix. |
Call graph
leaf_peers
The leaves of the peer realm that face the seam leaf code of this_realm (issue #110, P3): idx(1:n), indices into peer_codes (the peer's seam leaves), those whose tangential extent overlaps the leaf's by more than half a cell, and k, log2 of the leaf's cell size over theirs (0 equal, +1 the peers twice as fine, -1 twice as coarse). Stops when the peers do not share one cell size, or when it is not the leaf's, half or twice it.
fortran
subroutine leaf_peers(this_realm, face, code, peer, peer_codes, idx, n, k)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm of the leaf. | |
face | integer(kind=I4P) | in | Seam face of this_realm (FACE_* code). | |
code | integer(kind=I8P) | in | Seam leaf. | |
peer | class(realm_object) | in | Peer realm. | |
peer_codes | integer(kind=I8P) | in | Seam leaves of the peer (seam_leaf_codes). | |
idx | integer(kind=I4P) | out | allocatable | Overlapping peers. |
n | integer(kind=I4P) | out | Number of overlapping peers. | |
k | integer(kind=I4P) | out | log2(leaf cell size / peer cell size). |
Call graph
check_mixed_seam
Check a seam with mixed levels along it (coupling = auto left unresolved, issue #110 P3), face by face: every seam leaf of each side faces cells of one size, equal to its own, half or twice it (leaf_peers); equal cells cover its face exactly; finer peers are its 2:1 quadrants (half its tangential extent, starting at its origin or at its midpoint) and cover it; a coarser peer holds it as one of its quadrants. The requirements of a 2:1 face that do not depend on the levels (block cell counts, seam fill and restriction) are checked by resolve_auto_couplings; the stencil footprints are checked here, on the realms that are coarse or fine at some 2:1 face (as check_couplings does for coupling = refined).
fortran
subroutine check_mixed_seam(realm, pair, pfx)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | in | Forest realms. | |
pair | type(forest_face_pair_t) | in | Face pair (coupling = auto, mixed). | |
pfx | character(len=*) | in | Error message prefix. |
Call graph
build_seam_rows
Build the seam ghost rows of every realm from the replicated trees (issue #40).
Every rank walks, for every face pair (side A then side B), every leaf of the realm owning the ghosts that lies on the seam face, owned or not, and every ghost of its slab (tangential edge and corner ghosts included), in the tree's own order: the same sequence on every rank. The peer cell is the interior cell of the leaf of the peer realm containing the ghost centre (get_closest_block on the peer's replicated tree); ghosts outside the peer domain are corners where the seam meets a physical boundary and are left to the physical BC. Each rank keeps the rows it takes part in:
- local (ghost and cell here):
[peer, b_cell, b_ghost, i_cell, j_cell, k_cell, i_ghost, j_ghost, k_ghost]; - receive (ghost here, cell on rank r):
[r, b_ghost, i_ghost, j_ghost, k_ghost]on the ghost realm; - send (cell here, ghost on rank r):
[r, b_cell, i_cell, j_cell, k_cell]on the cell realm.
Since the order is shared, the rows rank A sends to rank B for a seam are, in order, the rows B receives from A. The peer cell centre must coincide with the ghost centre: mirror seams join cells of the same size.
fortran
subroutine build_seam_rows(realm, manifest)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | inout | Forest realms. | |
manifest | type(forest_manifest_t) | in | Parsed manifest. |
Call graph
enumerate_seam_side
Enumerate the seam ghosts of realm is on face, whose peer is realm ip; append this rank's rows.
fortran
subroutine enumerate_seam_side(realm, is, ip, face, local, recv, send)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | inout | Forest realms. | |
is | integer(kind=I4P) | in | Realm owning the ghosts. | |
ip | integer(kind=I4P) | in | Realm owning the cells. | |
face | integer(kind=I4P) | in | Seam face of realm is (FACE_* code). | |
local | type(seam_rows_t) | inout | Local rows of realm is. | |
recv | type(seam_rows_t) | inout | Receive rows of realm is. | |
send | type(seam_rows_t) | inout | Send rows of realm ip. |
Call graph
store_seam_rows
Store the enumerated seam rows of realm is into its maps, grouped by peer slot (and by rank inside a slot).
fortran
subroutine store_seam_rows(realm, is, manifest, local, recv, send)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | class(realm_object) | inout | Realm is. | |
is | integer(kind=I4P) | in | Realm index. | |
manifest | type(forest_manifest_t) | in | Parsed manifest. | |
local | type(seam_rows_t) | in | Local rows (col 1 = peer realm). | |
recv | type(seam_rows_t) | in | Receive rows (col 1 = peer realm). | |
send | type(seam_rows_t) | in | Send rows (col 1 = ghost realm). |
Call graph
group_rows
Group cross-rank rows [peer, rank, b, i, j, k, ...] by peer slot and, inside a slot, by ascending rank, keeping the enumeration order within a rank; store them without the peer column ([rank, b, i, j, k], plus kind, meta for send rows).
fortran
subroutine group_rows(rows, peers, cell, row_start, row_count)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
rows | type(seam_rows_t) | in | Enumerated rows. | |
peers | integer(kind=I4P) | in | Peer realm of each slot. | |
cell | integer(kind=I4P) | out | allocatable | Grouped rows. |
row_start | integer(kind=I4P) | out | allocatable | First row of each slot. |
row_count | integer(kind=I4P) | out | allocatable | Rows of each slot. |
Call graph
realm_face_leaves
Morton codes of the leaves of a realm that lie on one face of its domain, in tree order (issue #51).
fortran
subroutine realm_face_leaves(this_realm, face, codes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
face | integer(kind=I4P) | in | Face code (FACE_X_MIN..FACE_Z_MAX). | |
codes | integer(kind=I8P) | out | allocatable | Leaves on the face. |
Call graph
push_row
Append a row to a growable row list (the capacity doubles when full).
fortran
subroutine push_row(list, row)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
list | type(seam_rows_t) | inout | Row list. | |
row | integer(kind=I4P) | in | Row to append. |
Call graph
leaf_metrics
Origin, cell size and (optionally) upper corner of the leaf code of a realm, from its tree and grid (valid on every rank, whichever rank owns the leaf).
fortran
subroutine leaf_metrics(this_realm, code, emin, dxyz, emax)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
code | integer(kind=I8P) | in | Leaf Morton code. | |
emin | real(kind=R8P) | out | Leaf origin. | |
dxyz | real(kind=R8P) | out | Cell size. | |
emax | real(kind=R8P) | out | optional | Leaf upper corner. |
Call graph
ghost_slab_extents
The (i, j, k) bounds of a block's ghost slab on one face: ngc cells deep on the (axis, sgn) face, the two tangential axes over the full ghost-extended range [1-ngc, n+ngc] (edge and corner ghosts included).
Attributes: pure
fortran
subroutine ghost_slab_extents(this_realm, axis, sgn, imin_g, imax_g, jmin_g, jmax_g, kmin_g, kmax_g)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
axis | integer(kind=I4P) | in | Face axis and side. | |
sgn | integer(kind=I4P) | in | Face axis and side. | |
imin_g | integer(kind=I4P) | out | Slab bounds. | |
imax_g | integer(kind=I4P) | out | Slab bounds. | |
jmin_g | integer(kind=I4P) | out | Slab bounds. | |
jmax_g | integer(kind=I4P) | out | Slab bounds. | |
kmin_g | integer(kind=I4P) | out | Slab bounds. | |
kmax_g | integer(kind=I4P) | out | Slab bounds. |
Call graph
wrap_periodic_tangential
Wrap a seam ghost centre into the peer domain along every tangential axis periodic on both realms (issue #65 P4).
The edge and corner ghosts of a seam slab past a tangential boundary of the ghost realm lie outside the peer domain too. At a physical boundary they are the BC's; at a periodic one no BC fills them (the realm's own maps have no neighbour across the seam), and they kept their initial values, read by every stencil with tangential reach (the dissipative fluxes: NaN at the first step of a mirror split periodic in y). Their peer is the cell one period away, which the wrap makes get_closest_block find. Both realms span the same tangential extent at a mirror or refined seam (the faces cover each other), so the period is the peer's domain length.
Attributes: pure
fortran
subroutine wrap_periodic_tangential(realm_g, realm_c, axis, xg)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm_g | class(realm_object) | in | Realm owning the ghost. | |
realm_c | class(realm_object) | in | Realm owning the cells. | |
axis | integer(kind=I4P) | in | Seam normal axis. | |
xg | real(kind=R8P) | inout | Ghost centre. |
Call graph
register_intra_realm_amr_seams
Register every intra-realm AMR coarse-fine face in the forest flux register.
Walks each realm's tree node neighborhood (already built by make_neighborhood at realm init) and, for every block whose face neighbor is MORE refined (NODE_MORE_REFINED — this block is the COARSE side of a 2:1 jump), adds one register entry. The fine-side blocks (the ratio/2 finer neighbors covering that coarse face) are recorded in fine_block(:).
Only the 6 faces (fec = 1..6) are registered — reflux is a face-flux correction; edge/corner adjacencies (fec = 7..26) carry no conserved face flux and are skipped.
Two-pass, mirroring register_inter_realm_seams:
- Pass 1 counts coarse-side faces across all realms → register size.
- Pass 2 calls
register_face(seam_kind = SEAM_KIND_INTRA_REALM_AMR, ...)and fills the signedinter_realm_face_register_indexlookup:+cursoron the coarse (block, bc_fec),-cursoron each fine neighbor block's opposite face. For intra-realm jumps coarse and fine are the SAME realm, socoarse_realm = fine_realm = is.
Register ownership. This routine is the sole initializer of the flux register: it calls flux_register%initialize with the intra-realm face count (possibly 0, which still flips the register's is_initialized_ so the per-step reset/reflux hooks are safe no-ops) plus extra_faces.
Composition with inter-realm seams (issue #37). The manifest path calls it first with extra_faces = the inter-realm seam face count, then register_inter_realm_seams appends those faces after the nfaces_intra intra-realm ones. Both lists are walked on the replicated trees (issue #40), so every rank holds the same faces under the same cursors, which is what the register's cross-rank reduction of the fine sums relies on.
fortran
subroutine register_intra_realm_amr_seams(self, realm, extra_faces, nfaces_intra)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | Initialized realms whose trees are walked. | |
extra_faces | integer(kind=I4P) | in | optional | Register slots reserved for inter-realm faces. |
nfaces_intra | integer(kind=I4P) | out | optional | Intra-realm AMR faces registered (cursors 1..n). |
Call graph
apply_reflux_corrections
Dispatch the Berger-Colella reflux correction to every realm.
Called once per step AFTER close_step_forest's update_q. The forest's role is purely orchestration: it iterates the realm array and invokes each realm's apply_reflux_to_stage_forest TBP, passing that realm's OWN final stage (stages_per_step_forest()) so the realm-side end-of-step gate (stage == self%rk%nrk) fires for every realm, asymmetric-K included. The realm-side body filters flux_register%face(:) by face%coarse_realm == self%realm_index and adds the per-cell end-of-step correction directly into its committed self%q (full dt/dx weight, no stage RK coefficient — AMReX Berger-Colella cadence).
The forest never reaches realm%rk/realm%q directly: the per-cell write lives realm-side. This is the integrator-agnostic split — see realm_object%apply_reflux_to_stage_forest for the contract, and prism_cpu_object for the RK-specific override.
Empty register fast path: when the register has no faces the per-realm calls each short-circuit on flux_register%nfaces == 0.
fortran
subroutine apply_reflux_corrections(self, realm, dt)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | in | The forest (holds the flux register). | |
realm | type(realm_pointer) | inout | Realms; each realm's reflux TBP fires once. | |
dt | real(kind=R8P) | in | Time step. |
Call graph
share_flux_register
Copy the flux register into every realm (realm_object%flux_register_copy), after each build (init, regrid, manifest): the faces, their ownership and their accumulators (zeroed), so that a realm can accumulate one residual evaluation's seam fluxes for a diagnostic without touching the forest's step accumulators (issue #68 A2). The register is replicated (the same faces on every rank, issue #40), and so is the copy.
fortran
subroutine share_flux_register(self, realm)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
self | class(forest_object) | inout | The forest. | |
realm | type(realm_pointer) | inout | Realms. |
Call graph
Functions
seam_leaf_codes
The codes of the leaves of a realm along a seam face, in tree order (issue #110). The balance works on this list (tree%node(code)), not on a face test inside the tree traversal: that loop shape was miscompiled by nvfortran 26.9 (-fast, -gpu=lto) in this routine, which then found no leaf on the face, at random, run after run.
Returns: integer(kind=I8P)
fortran
function seam_leaf_codes(this_realm, face) result(codes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
face | integer(kind=I4P) | in | Seam face (FACE_* code). |
Call graph
cell_ratio_log2
log2 of the ratio of the seam cell sizes of two sides, a over b, along the seam normal (issues #110, #71): 0 for equal cells, 1 when side a is twice as coarse.
Returns: integer(kind=I4P)
fortran
function cell_ratio_log2(realm_a, face_a, realm_b, face_b) result(k)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm_a | class(realm_object) | in | Realms. | |
face_a | integer(kind=I4P) | in | Seam faces (FACE_* codes). | |
realm_b | class(realm_object) | in | Realms. | |
face_b | integer(kind=I4P) | in | Seam faces (FACE_* codes). |
Call graph
tree_marks_text
The refine/derefine mark counts of a replicated tree, r/d (the regrid log of a multi-realm forest, issue #110).
Returns: character(len=32)
fortran
function tree_marks_text(tree) result(text)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
tree | type(tree_object) | in | Tree. |
Call graph
tree_has_marks
Whether some leaf of a replicated tree is marked to refine or derefine (issue #110).
Returns: logical
fortran
function tree_has_marks(tree) result(yes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
tree | type(tree_object) | in | Tree. |
Call graph
seam_cell_size
The cell size of the leaves of a realm on its seam face: one size for all of them, error_stop otherwise; with uniform present, uniform = .false. instead of the stop when the sizes differ (a mixed-level side, issue #110).
Returns: real(kind=R8P)
fortran
function seam_cell_size(this_realm, face, pfx, uniform) result(dxyz)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
face | integer(kind=I4P) | in | Seam face (FACE_* code). | |
pfx | character(len=*) | in | Error message prefix. | |
uniform | logical | out | optional | One cell size on the side. |
Call graph
is_2to1_piece
Whether the tangential extent [emin_f, emax_f] of a fine seam leaf is one 2:1 piece of the coarse leaf's [emin_c, emax_c] (issue #71): half the coarse extent, starting at its origin or at its midpoint, along a refined axis (r == 2); the same extent along a null one (r == 1, a quadtree's z).
Attributes: pure
Returns: logical
fortran
function is_2to1_piece(emin_c, emax_c, emin_f, emax_f, r, tol) result(yes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
emin_c | real(kind=R8P) | in | Coarse leaf extent along the tangential axes. | |
emax_c | real(kind=R8P) | in | Coarse leaf extent along the tangential axes. | |
emin_f | real(kind=R8P) | in | Fine leaf extent along the same axes. | |
emax_f | real(kind=R8P) | in | Fine leaf extent along the same axes. | |
r | integer(kind=I4P) | in | Refinement ratio along the same axes. | |
tol | real(kind=R8P) | in | Geometric tolerance. |
Call graph
pair_refine_ratio
The refinement ratio per axis a 2:1 seam between two realms uses (issue #71): maps%refine_ratio of both, which must agree (the same tree kind: octree, quadtree or binary tree), and 2 along the seam normal (a seam across a null axis has no second level to join). Stops otherwise.
Returns: integer(kind=I4P)
fortran
function pair_refine_ratio(r_a, r_b, face_a, pfx) result(r)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
r_a | class(realm_object) | in | The two realms. | |
r_b | class(realm_object) | in | The two realms. | |
face_a | integer(kind=I4P) | in | Seam face of r_a (FACE_* code). | |
pfx | character(len=*) | in | Error message prefix. |
Call graph
seam_register_faces
The inter-realm register faces of a face pair (issue #110 P3), in a canonical order on the replicated trees: one per seam leaf of the coarse side, in tree order, for a mirror or refined pair (the coarse side: seam_sides); for a pair with mixed levels (auto left unresolved), one per seam leaf of realm_a facing equal cells (a mirror face, realm_a coarse by convention) or finer cells (a 2:1 face, realm_a coarse), then one per seam leaf of realm_b facing finer cells (a 2:1 face, realm_b coarse). Each face carries its own coarse and fine sides.
Returns: type(seam_register_face_t)
fortran
function seam_register_faces(realm, pair) result(faces)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
realm | type(realm_pointer) | in | Forest realms. | |
pair | type(forest_face_pair_t) | in | Face pair. |
Call graph
size_pairs
Number of face pairs of a manifest.
Attributes: pure
Returns: integer(kind=I4P)
fortran
function size_pairs(manifest) result(n)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
manifest | type(forest_manifest_t) | in | Parsed manifest. |
leaf_on_realm_face
Return .true. iff the leaf code of a realm has its (axis, sgn) face on the realm boundary (any owner rank).
Returns: logical
fortran
function leaf_on_realm_face(this_realm, code, axis, sgn) result(yes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm. | |
code | integer(kind=I8P) | in | Leaf Morton code. | |
axis | integer(kind=I4P) | in | Face axis (1..3) and side (+1 max, -1 min). | |
sgn | integer(kind=I4P) | in | Face axis (1..3) and side (+1 max, -1 min). |
Call graph
inside_domain
Return .true. iff xc lies inside the domain of this_realm, at least tol away from its boundary.
Attributes: pure
Returns: logical
fortran
function inside_domain(this_realm, xc, tol) result(yes)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
this_realm | class(realm_object) | in | Realm to query. | |
xc | real(kind=R8P) | in | Point. | |
tol | real(kind=R8P) | in | Per-axis margin. |
Call graph
ghost_label
Name a seam ghost cell in an error message.
Returns: character(len=:)
fortran
function ghost_label(is, b, i, j, k) result(label)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
is | integer(kind=I4P) | in | Realm index. | |
b | integer(kind=I4P) | in | Owner-local block and ghost cell indices. | |
i | integer(kind=I4P) | in | Owner-local block and ghost cell indices. | |
j | integer(kind=I4P) | in | Owner-local block and ghost cell indices. | |
k | integer(kind=I4P) | in | Owner-local block and ghost cell indices. |
Call graph