Gate shifted velocity Jets to all-blocked callers

This commit is contained in:
Codex committed 2026-10-17 00:46:49 -07:00
1 parent b77f2238dd
commit 9dddf5d812
7 files changed
+340 -17

No files matched your search

+5 -2
View File
@@ -189,13 +189,14 @@ def edge_to_node_frame(points):
def surface_link_velocity(objects, cfg, flags, fluid_idx, dir, body_id, rx, ry,
jets=(), hits=None):
jets=(), hits=None, *, _shifted_blocked=False):
"""Per-link prescribed surface velocity (n, 2) FP32 and aperture mask.
Host-only and storage-neutral: rows follow the given physical cut-link
order. Returns (None, None) when neither an object carries surface
actuation nor a jet is given. Jets need true FP64 ``hits`` (n, 2) and may
not share a link with each other or with a legacy aperture.
Shifted storage is privately enabled only by the all-blocked stepper.
"""
enabled = [obj for obj in objects if obj.surface_actuation is not None]
if not enabled and not jets:
@@ -219,7 +220,9 @@ def surface_link_velocity(objects, cfg, flags, fluid_idx, dir, body_id, rx, ry,
if hits is None or len(hits) != len(dir):
raise ValueError("Jets require true hit points row-aligned with the cut links")
if (cfg is None or not cfg.is_d2q9 or cfg.store_precision != "FP32"
or cfg.streaming != "double_buffer" or cfg.ddf_shifting):
or cfg.streaming != "double_buffer"
or (cfg.ddf_shifting and not (_shifted_blocked is True
and cfg.collision == "SRT" and not cfg.les_enabled))):
raise ValueError("Jets require D2Q9/FP32/unshifted/double_buffer")
shape, jet_id = jet_link_shapes(jets, hits)
driven = jet_id >= 0
+2 -2
View File
@@ -422,7 +422,7 @@ def _circle_in_coverage(covered, cx, cy, radius):
def prepare_fine_boundary(cfg, patch, objects, *, wall_aware=False, jets=(),
parent_origin=(0., 0.), parent_spacing=1.):
parent_origin=(0., 0.), parent_spacing=1., _shifted_blocked=False):
"""Project fixed circles and reject boundary/transfer overlap before CUDA.
Input centers/radii and Jets are in the root edge frame. ``parent_origin``
@@ -555,7 +555,7 @@ def prepare_fine_boundary(cfg, patch, objects, *, wall_aware=False, jets=(),
jet_cfg.validate()
fluid_idx, dirs, _, body_id, rx, ry, _, _ = packed
surface_link_velocity(local, jet_cfg, flags, fluid_idx, dirs, body_id, rx, ry,
jets=jets, hits=hits)
jets=jets, hits=hits, _shifted_blocked=_shifted_blocked)
return FineBoundary2D(tuple(local), _readonly(flags, np.uint16),
tuple(_readonly(a, a.dtype) for a in packed),
_readonly(sorted(boundary), np.uint32),
+12 -6
View File
@@ -287,11 +287,12 @@ class FixedPatchStepper:
pair = pairs[level - 1]
if level == 1:
host = prepare_fine_boundary(cfg, pair, level_objects[1],
wall_aware=self._wall_aware, jets=level_jets[1])
wall_aware=self._wall_aware, jets=level_jets[1],
_shifted_blocked=self._ddf_shifting)
else:
host = prepare_fine_boundary(self._level_cfgs[level - 1], pair, level_objects[level],
jets=level_jets[level], parent_origin=origin,
parent_spacing=spacing)
parent_spacing=spacing, _shifted_blocked=self._ddf_shifting)
self._boundary_hosts.append(host)
origin = tuple(o + spacing * f for o, f in zip(origin, pair.fine_origin))
spacing /= 2
@@ -309,7 +310,8 @@ class FixedPatchStepper:
self._level_jets = level_jets
self._level_boundaries = [None] + [
_prepare_blocked_boundary(self._boundary_hosts[level], self._layouts[level],
self._level_cfgs[level], level_jets[level])
self._level_cfgs[level], level_jets[level],
_shifted_blocked=self._ddf_shifting)
for level in range(1, depth)]
self._leaf = [kind == ACTIVE for kind in self.hierarchy.kinds]
for level in range(1, depth):
@@ -558,6 +560,7 @@ class FixedPatchStepper:
with self._lock:
self._require("ready")
self._check_storage()
pairs = self.hierarchy.pairs
if (self._wall_aware or self.hierarchy.depth != 3
or not isinstance(pairs[1], FixedPatchSet2D)
@@ -569,19 +572,22 @@ class FixedPatchStepper:
actual = self._level_boundaries[2]
jets = () if actual is None else actual.jets
old = RemapTopology.from_config(cfg, pairs[0], pairs[1].bounds,
child_objects=child_objects, child_jets=jets)
child_objects=child_objects, child_jets=jets,
_shifted_blocked=self._ddf_shifting)
if (not same_physical_boundary(old.boundary, self._boundary_hosts[2])
or (self._boundary_hosts[2] is not None and actual is None)):
raise ValueError("child_objects must reproduce the original root-edge-frame boundary")
if actual is not None:
velocity = actual.tables.get("surface_velocity")
if velocity is None:
velocity = boundary_velocity(cfg, pairs[1], actual.host, jets)
velocity = boundary_velocity(cfg, pairs[1], actual.host, jets,
_shifted_blocked=self._ddf_shifting)
if (not same_physical_boundary(old.boundary, actual.host)
or not np.array_equal(old.surface_velocity, velocity)):
raise ValueError("child_objects changed boundary ownership or surface velocity")
new = RemapTopology.from_config(cfg, pairs[0], rectangles,
child_objects=child_objects, child_jets=jets)
child_objects=child_objects, child_jets=jets,
_shifted_blocked=self._ddf_shifting)
if (not same_physical_boundary(old.boundary, new.boundary)
or not np.array_equal(old.surface_velocity, new.surface_velocity)):
raise ValueError("remap requires the identical pinned physical boundary and BFL support")
+2 -2
View File
@@ -87,7 +87,7 @@ class _BlockedBoundary:
accumulate: object = None
def _prepare_blocked_boundary(boundary, layout, cfg, jets):
def _prepare_blocked_boundary(boundary, layout, cfg, jets, *, _shifted_blocked=False):
if boundary is None or layout is None:
return None
fluid_idx, dirs, q, body_id, rx, ry, _, fallback = boundary.curved_host
@@ -102,6 +102,6 @@ def _prepare_blocked_boundary(boundary, layout, cfg, jets):
cfg.validate()
tables["surface_velocity"], tables["aperture"] = surface_link_velocity(
boundary.objects, cfg, boundary.flags, fluid_idx, dirs, body_id, rx, ry,
jets=jets, hits=boundary.curved_hits)
jets=jets, hits=boundary.curved_hits, _shifted_blocked=_shifted_blocked)
return _BlockedBoundary(boundary, tables, jets, actuated,
jet_link_shapes(jets, boundary.curved_hits) if jets else None)
+6 -5
View File
@@ -39,7 +39,7 @@ class RemapTopology:
@classmethod
def from_config(cls, cfg, parent, child_rectangles, *, coarse_boundary="periodic", objects=(),
child_objects=(), child_jets=()):
child_objects=(), child_jets=(), _shifted_blocked=False):
if coarse_boundary != "periodic" or tuple(objects) or cfg.nz != 1:
raise ValueError("remap requires periodic 2D state; use child_objects for a pinned L2 body")
if type(parent) not in (FixedPatch2D, FixedPatchSet2D):
@@ -51,7 +51,7 @@ class RemapTopology:
viscosity=2 * cfg.viscosity)
boundary = prepare_fine_boundary(
fine_cfg, child, child_objects, jets=child_jets,
parent_origin=parent.fine_origin, parent_spacing=.5)
parent_origin=parent.fine_origin, parent_spacing=.5, _shifted_blocked=_shifted_blocked)
pinned, velocity = (), None
child_leaf = child.fine_kind == ACTIVE
if boundary is not None:
@@ -67,7 +67,8 @@ class RemapTopology:
if match is not None:
containing.add(match)
pinned = tuple(sorted(containing))
velocity = boundary_velocity(cfg, child, boundary, child_jets)
velocity = boundary_velocity(cfg, child, boundary, child_jets,
_shifted_blocked=_shifted_blocked)
if velocity is not None:
velocity.setflags(write=False)
masks = (~parent.covered, middle_kind == ACTIVE, child_leaf)
@@ -76,7 +77,7 @@ class RemapTopology:
return cls(parent, child, masks, boundary, pinned, velocity)
def boundary_velocity(cfg, child, boundary, jets=()):
def boundary_velocity(cfg, child, boundary, jets=(), *, _shifted_blocked=False):
"""Physical cut-link order; never blocked addresses or stale Jet snapshots."""
local_cfg = replace(cfg, nx=child.fine_shape[1], ny=child.fine_shape[0],
viscosity=4 * cfg.viscosity)
@@ -84,7 +85,7 @@ def boundary_velocity(cfg, child, boundary, jets=()):
fluid, dirs, _, ids, rx, ry, _, _ = boundary.curved_host
velocity, _ = surface_link_velocity(
boundary.objects, local_cfg, boundary.flags, fluid, dirs, ids, rx, ry,
jets=jets, hits=boundary.curved_hits)
jets=jets, hits=boundary.curved_hits, _shifted_blocked=_shifted_blocked)
return velocity