Skip to content

Runtime AMR on a forest ​

IDGroupMilestoneBackendsFigureRegression
multirealm legs 7–13Euler#110 P1–P5CPU, FNLyes—

Case and scope ​

The realms of a forest regrid during the time loop, each by its own [amr] section. At a regrid step:

  • every realm marks its blocks;
  • the forest balances the marks across the seams;
  • every realm adapts;
  • the inter-realm topology (register faces, seam ghost rows, boundary crown, device maps) is rebuilt from the new trees.

The forest cookbook, R12 describes the mechanism; the forest concepts give the rules.

A mirror or refined seam keeps one level per seam side. A coupling = auto seam is decided from the cells at every topology build, and its levels may differ along it, face by face (equal cells or 2:1).

The legs extend the multi-realm runs of legs 1–6. Where the blocks of the realms can match a single-realm run, the union must reproduce that run bit for bit. Where they cannot (2-D realms whose roots are not square), the legs assert invariants:

  • conservation in a closed box;
  • the same run on 1 and 2 ranks;
  • the same run with the topology rebuilt after every step (ADAM_FOREST_REBUILD_TOPOLOGY=1, a test hook);
  • a restart across regrids.

What the legs catch:

  • marking across a seam: the forest fills the seams before the realms mark, so a ghost-reading marker sees the peer realm (leg 7);
  • the cross-realm balance: a seam turning 2:1 and back as Sod's waves cross it (leg 8). The balance compares cell sizes, not levels, so equal cells may sit at different levels (leg 9);
  • refinement criteria the program registers (leg 10);
  • mixed levels along a seam: 2:1 faces in both directions on one seam (leg 11), and a refined patch moving along a seam (leg 12). The balance counts the neighbours that touch at an edge or a corner, since the seam slab's edge and corner ghosts read them; leg 12's first runs found that gap;
  • restart across regrids (leg 13).

Models and numerics ​

ItemChoiceCode
Regrid of a forestthe realm phases run by the forest: mark, balance, adapt, rebuild, sweep after sweepregrid_realms, balance_seam_marks, balance_mixed_pair, adam_forest_object.F90
Mixed seamper-face register faces and checkscheck_mixed_seam, leaf_peers, seam_register_faces, adam_forest_object.F90
MarkersLöhner on the density (legs 8, 9, 12), primitive boxes (legs 7, 10, 11), a registered criterion (leg 10)mark_runtime, adam_flume_cpu_object.F90
Seam cadenceβ (stage_coincident) in every legcookbook R4

Initial and boundary conditions ​

LegProblemForestReferenceRanks
7Sod, leg 2's inputs, [amr] frequency = 4 in realm 2 (a box marker: the regrids keep the grid)mirrorsod-amr2
8Sod split at the diaphragm, Löhner (refine 0.3, derefine 0.1), a regrid every 4 steps, levels 1–2 in the realms (2–3 in the single run)autothe single Sod with the same marker; seam_ghost_fill = injection and tricubic2
9leg 5's forest (misaligned blocks), equal cells at levels 2–3 and 1–2, Löhnermirrorconservation2
10a registered criterion (mode = 6) voting as the box marker, on one realm and on leg 2's forestmirrorthe built-in box marker2
11leg 8's grids, a box next to the seam in each realm over half of it (2:1 faces in both directions), a regrid every 4 stepsautothe single realm with the same boxes2
12the isentropic vortex (radius 0.07) at (0.47, 0.3), free stream (0, 1) along the seam, [0,1]2×[0,0.5] split at x=0.5, octree 8×16×8 cells per block, levels 1–3, Löhner, a regrid every 5 steps, t=0.3; y periodic, x inviscid walls, z extrapolated with w=0 (a closed box)autoconservation, ranks, hook1, 2
13leg 12's case, 195 steps against 155 + restart + 40 (the restart at a regrid that coarsens and leaves 2:1 faces on the seam; a regrid into a new grid at step 190)autothe uninterrupted run2 (and 1: refused)

Input files ​

FileRole
src/tests/flume/verification/multirealm/check.shruns the legs (--legs leg7 ... leg13; FLUME_EXE selects the backend; leg 10 needs exe/test_flume_user_criterion)
src/tests/flume/verification/multirealm/make_vortex_forest.pythe forest of legs 12 and 13 (--it-save N for the figure)
src/tests/flume/verification/multirealm/multirealm_oracle.pythe union against the single-realm run cell by cell (tolerance 0 unless stated), and the summed conservation histories
src/tests/flume/verification/make_doc_runs.sh <runs> multirealm-amr, make_doc_figures.py --only multirealm-amrre-runs leg 12's case with a checkpoint every 20 steps and draws the figure (about 6 min)
bash
cd src/tests/flume/verification/multirealm
./check.sh --legs leg2,leg7,leg8,leg9,leg10,leg11,leg12,leg13          # CPU (leg 7 compares against leg 2's run)
FLUME_EXE=$PWD/../../../../../exe/adam_flume_fnl ./check.sh --legs leg8,leg9,leg11,leg12,leg13    # FNL

Results ​

Runtime AMR on a forest

Leg 12's case, CPU, 2 ranks, a checkpoint every 20 steps. Top: the density and the blocks of both realms at three steps; the seam is the dashed line at x=0.5, and the refined patch moves along it with the vortex. Bottom left: the mass of each realm and the drift of their sum. Bottom right: the blocks per level in each realm.

Measured on the development box (WSL), 2026-10-29:

LegCheckBoundCPUFNL
7union against sod-amr with a regridding realmbitwisebitwise—
8union against the single run, seam_ghost_fill = injectionbitwisebitwisebitwise
8the same, tricubic fill10−121.7⋅10−131.3⋅10−13
9mass of the two realms, the seam stays a mirror10−122.0⋅10−164.0⋅10−16
10registered criterion against the built-in marker, one realm and the forestbitwisebitwise— (CPU driver)
11union against the single run, injection; and with the topology rebuilt every stepbitwisebitwisebitwise
11the same, tricubic fill10−121.5⋅10−139.3⋅10−14
12mass of the two realms over 519 steps10−121.1⋅10−161.1⋅10−16
121 rank and the rebuilt topology against 2 ranksbitwisebitwisebitwise
12the seam mixed, the grid refined and coarsenedat least one eachthe seam mixed at 25 topology builds; 15 realm regrids at 13 steps, 7 refining and 9 coarsening (one both)the same
13restarted against uninterrupted: fields, historiesbitwise, identicalbitwise, identicalbitwise, identical
13restart on fewer ranks than savedrefusedrefusedrefused

The tricubic legs differ from the single realm only next to the 2:1 faces. One level lower, the realms' coarse blocks are larger in y and z, which moves the 4-point footprints of their 2:1 faces within the block; the same constant-in-y data is then summed with other weights.

Findings ​

  • Edge and corner neighbours (leg 12). Leg 12's first octree runs stopped at step 10. A tangential edge ghost of a realm-1 seam block at level 3 fell on a realm-2 block at level 1, four times coarser. The balance compared only leaves whose faces overlap, while the seam slab's edge and corner ghosts also read the diagonal neighbours. It now counts neighbours that touch at an edge or a corner, including across a tangential axis periodic in both realms.
  • A closed box for a conservation bound. Leg 12 was first designed with extrapolated x faces and drifted by 2.7⋅10−6: the vortex tail carried mass through the open boundaries. The net boundary flux of the final cells matched the measured mass change. A drift bound needs a closed box; inviscid walls give one.
  • Restart and cadence (leg 13). Every leg here uses β seams. When this page was written an end_of_step (α) seam was filled into the committed state only, never into the Runge–Kutta stage buffers, so a restarted α forest differed at the seam from its first step, and α and β differed by 18–45 % next to the seam after four steps. Fixed by #113: multirealm/check.sh leg 14 measures α against β and restarts an α forest bitwise (cookbook R4).
  • Inter-realm 2:1 faces need the same tree kind in both realms and a seam normal to a refined axis. Quadtrees and binary trees are accepted since #71 (static 2:1 seams checked by multirealm/check.sh leg 15; this page's runtime legs run on octrees).