89 lines
4.4 KiB
Markdown
89 lines
4.4 KiB
Markdown
# Fixed three-level rectangle unions
|
|
|
|
This page describes the legacy three-level entry point of `FixedPatchStepper`,
|
|
with rectangle unions on either adjacent pair. The `refinements` level-list
|
|
entry point also supports arbitrary depth; three or more levels require
|
|
all-blocked storage and bodies/Jets only on the finest level. This is not
|
|
general AMR: there is no per-region timestep, moving geometry, automatic
|
|
dynamic refinement or L1 body support in the three-level form.
|
|
All regions share one current/spare buffer pair per level. The existing schedule
|
|
advances L0 once, L1 twice and L2 four times per base step, with aggregate transfers.
|
|
No CUDA kernel changes are involved.
|
|
|
|
## Explicit coordinate frames
|
|
|
|
Keep the existing scalar `child=(x0,y0,x1,y1)` for a single scalar parent patch.
|
|
Its coordinates retain their original meaning: half-open integer indices in the
|
|
allocated L1 window, including its ghost band.
|
|
|
|
The new keyword `child_rectangles_in_parent=[...]` is mutually exclusive with
|
|
`child`. It accepts a scalar or a set parent and interprets every rectangle in
|
|
the actual allocated L1 array, including ghost bands and holes. It never infers
|
|
region-local coordinates. The physical root cell edge corresponding to an L1
|
|
index `(x,y)` is `parent.fine_origin + (x,y)/2`:
|
|
|
|
- A scalar L1 parent has a shifted window origin.
|
|
- A set L1 parent has origin `(0,0)` and public shape `(2*ny,2*nx)`.
|
|
- A child set has public shape twice the allocated L1 shape. Its root origin is
|
|
the L1 allocated origin, even when the parent is a scalar window.
|
|
|
|
For a 16x16 root, scalar parent `(4,4,12,12)` and scalar child `(8,8,16,16)`
|
|
are physically equivalent to parent set `[(4,4,12,12)]` with child set
|
|
`[(12,12,20,20)]`. A child set on the *scalar* parent instead uses
|
|
`[(8,8,16,16)]`. Reusing the same numbers after changing the parent frame can
|
|
move the physical region.
|
|
|
|
Both adjacent pairs are built from their unions, without a fixed rectangle-gap
|
|
rule. Adjacent, overlapping and concave unions are accepted only when their
|
|
actual transfer dependencies close. The whole child union must preserve
|
|
inherited ACTIVE coverage, uncovered ACTIVE donors/receivers, surviving pulls, and the upstream
|
|
restriction footprint. Sparse holes remain unowned; inherited INNER remains
|
|
stream-only and OUTER remains invalid. Block sizes must divide their allocated
|
|
level grids. Sparse storage owns every grid-aligned tile intersecting the union
|
|
plus its four-cell ghost band; rectangle and support edges need not align with
|
|
tile edges.
|
|
|
|
## Example
|
|
|
|
```python
|
|
run = FixedPatchStepper(
|
|
cfg, [(4, 4, 20, 28), (24, 4, 44, 28)], context=ctx,
|
|
base_block=(4, 4), fine_block=(4, 4), child_block=(4, 4),
|
|
child_rectangles_in_parent=[(16, 16, 32, 40), (56, 16, 80, 40)],
|
|
)
|
|
```
|
|
|
|
This example uses a 48x32 root. `initialize` and `download` use three Q-major
|
|
dense arrays. Public arrays and masks still scale with the full allocated
|
|
extent; sparse device buffers do not remove that host-memory limit.
|
|
|
|
Stationary whole-circle `child_objects` and `child_jets` use root edge
|
|
coordinates and a single L2 boundary object. Body IDs are physical object-list
|
|
positions, not region IDs or caller `obj_id`. Complete boundary stencils must
|
|
avoid the transfer footprint. Change a child Jet with
|
|
`set_jet_amplitude(index, value, level=2)`; L1 bodies/Jets remain unsupported.
|
|
|
|
## Verification
|
|
|
|
CPU geometry, table, pre-CUDA rejection, schedule and cleanup tests:
|
|
|
|
```sh
|
|
PYTHONPATH=src python -m unittest discover -s tests/unit -p 'test_refinement*.py' -v
|
|
```
|
|
|
|
`tests/unit/test_union_refinement.py` covers union dependencies and tile
|
|
ownership; `tests/unit/test_hierarchy.py` covers composed geometry through four
|
|
levels. `tests/unit/test_raw_exchange.py` checks the four-level host schedule
|
|
with CUDA mocks. These establish topology/control-flow coverage, not numerical
|
|
qualification at every depth or interface shape.
|
|
|
|
Explicit GPU gates are in
|
|
`tests/validation/multigrid/test_refinement_three_level_multipatch_gpu.py`.
|
|
They cover physical-frame equivalence, twins, asymmetric refinement, multiple
|
|
children, reversed order, independently varied aligned layouts, public/raw
|
|
masks and two L2 bodies with static/zero/driven/switched Jets. Snapshots are
|
|
0/1/2/8. CPU mocks do not execute CUDA and do not establish numerical accuracy.
|
|
GPU equivalence gates supplement the separately frozen independent dense
|
|
three-level numerical replay; passing either alone is not a conservation,
|
|
performance or physical-accuracy claim.
|