"""One-interval, collision-free population-basis analysis; NOT an LBM solver. No production imports/maps, CUDA, collision, force, or time-stepping benchmark. The hypotheses below extend the current geometric transfer to a wall crossing; they are not claims about the shipped backend or any external implementation. Run: python research/wall_seam_pulse_20261014/analyze.py """ from dataclasses import dataclass from pathlib import Path import csv import hashlib import json import resource resource.setrlimit(resource.RLIMIT_FSIZE, (2*1024**2, 2*1024**2)) OUT = Path(__file__).resolve().parent ROOT = OUT.parents[1] N, NF = 16, 24 LO, HI, HALO = 4, 12, 4 CX = (0, 1, -1, 0, 0, 1, -1, 1, -1) CY = (0, 0, 0, 1, -1, 1, -1, -1, 1) OPP = (0, 2, 1, 4, 3, 6, 5, 8, 7) def covered(x, y): return LO <= x < HI and LO <= y < HI def coarse_fluid(x, y): return 0 <= x < N and 8 <= y < 15 def fine_fluid(x, y): return 0 <= x < NF and 0 <= y < NF and 8 < 2+(y+.5)/2 < 15 def active(x, y): return HALO <= x < NF-HALO and HALO <= y < NF-HALO and fine_fluid(x, y) def parent(x, y): return LO+(x-HALO)//2, LO+(y-HALO)//2 def fine_targets(): return [(x, y) for y in range(2, NF-2) for x in range(2, NF-2) if fine_fluid(x, y)] @dataclass(frozen=True) class Packet: phase: str slot: tuple # (q, x, y) value: float operation: str parents: tuple = () # (Packet, coefficient); includes zero-valued inputs def derive(phase, slot, operation, parents): return Packet(phase, slot, sum(p.value*w for p, w in parents), operation, tuple(parents)) def initialize(pulse): level, q0, x0, y0 = pulse coarse = {(q, x, y): Packet('Gc0', (q, x, y), float(('coarse', q, x, y) == pulse), 'input') for y in range(N) for x in range(N) if coarse_fluid(x, y) and not covered(x, y) for q in range(9)} fine = {} for y in range(NF): for x in range(NF): # Full fine footprint: a shared parent and its four children must # agree, including outer halo and solid cells (which hold no data). px, py = parent(x, y) if fine_fluid(x, y) != coarse_fluid(px, py): raise AssertionError('parent/child physical classifications disagree') if not fine_fluid(x, y): continue for q in range(9): key = q, x, y if active(x, y): fine[key] = Packet('Gf0', key, float(('fine', q, x, y) == pulse), 'input') else: fine[key] = derive('Gf0', key, 'explode', [(coarse[q, px, py], 1)]) if level == 'coarse': assert sum(p.value for p in coarse.values()) == 1 else: assert active(x0, y0) and sum(p.value for p in fine.values() if p.operation == 'input') == 1 return coarse, fine def fine_hop(inp, hop, prestream=False): phase = ('pre_' if prestream else '')+f'F{hop}' staged = dict(inp) if prestream: written = set() # Independent prestream form: write the missing solid-source slots. # Each (q,source) has exactly one fluid destination in a pull scheme. for x, y in fine_targets(): for q in range(9): sx, sy = x-CX[q], y-CY[q] if not fine_fluid(sx, sy) and (OPP[q], x, y) in inp: key = q, sx, sy assert key not in written written.add(key) staged[key] = derive(phase+'_BCscratch', key, 'prestream_BB', [(inp[OPP[q], x, y], 1)]) out = {} for x, y in fine_targets(): for q in range(9): key, source = (q, x, y), (q, x-CX[q], y-CY[q]) if prestream or fine_fluid(source[1], source[2]): donor, op = staged.get(source), 'pull' else: donor, op = inp.get((OPP[q], x, y)), 'local_BB' if donor is not None: assert key not in out out[key] = derive(phase, key, op, [(donor, 1)]) # Missing slots are explicitly invalid, not zero; outer halo is not output. return out def links(): result = {} for y in range(N): for x in range(N): if not coarse_fluid(x, y) or covered(x, y): continue for q in range(1, 9): if LO <= x+.5-CX[q]/2 <= HI and LO <= y+.5-CY[q]/2 <= HI: a, b = HALO+2*(x-LO), HALO+2*(y-LO) result[q, x, y] = [(q, a+dx, b+dy) for dy in (0, 1) for dx in (0, 1)] return result LINKS = links() HYPOTHESES = ('coarse_BB_then_coalesce', 'coalesce_then_coarse_BB', 'omit_solid_source_links') def coarse_arrivals(gc, f2, hypothesis): out = {} for q, x, y in gc: key = q, x, y sx, sy = (x-CX[q]) % N, (y-CY[q]) % N wall = not coarse_fluid(sx, sy) transfer = key in LINKS if hypothesis == 'omit_solid_source_links' and wall: transfer = False # Functional final assignment models the specified ordered overrides. # Every destination has one final writer; this alone does not prove # that one initial packet has only one physical owner globally. if transfer and (not wall or hypothesis == 'coarse_BB_then_coalesce'): parents = [(f2[child], .25) for child in LINKS[key]] node = derive('Fc1', key, 'coalescence', parents) elif wall: node = derive('Fc1', key, 'coarse_BB', [(gc[OPP[q], x, y], 1)]) else: node = derive('Fc1', key, 'coarse_pull', [(gc[q, sx, sy], 1)]) assert key not in out out[key] = node return out def trace(p, contribution=1.): return dict(phase=p.phase, slot=list(p.slot), operation=p.operation, value=p.value, downstream_weight=contribution, parents=[trace(parent, contribution*w) for parent, w in p.parents if parent.value]) def main(): cases = [('outer_coarse_q7', ('coarse', 7, 2, 8)), ('adjacent_coarse_q7', ('coarse', 7, 3, 8)), ('active_fine_q7', ('fine', 7, 4, 12))] rows, results = [], [] for name, pulse in cases: gc, gf = initialize(pulse) f1 = fine_hop(gf, 1) f2 = fine_hop(f1, 2) pre1 = fine_hop(gf, 1, prestream=True) pre2 = fine_hop(pre1, 2, prestream=True) assert {k: p.value for k, p in f1.items()} == {k: p.value for k, p in pre1.items()} assert {k: p.value for k, p in f2.items()} == {k: p.value for k, p in pre2.items()} assert all(child in f2 for children in LINKS.values() for child in children) initial = 1. if pulse[0] == 'coarse' else .25 fine_mass = .25*sum(p.value for (q, x, y), p in f2.items() if active(x, y)) for phase in (gc, gf, f1, f2): for node in phase.values(): if node.value: rows.append((name, 'shared', node.phase, *node.slot, node.operation, node.value, ';'.join(f'{p.phase}:{p.slot}*{w}' for p, w in node.parents))) for hypothesis in HYPOTHESES: out = coarse_arrivals(gc, f2, hypothesis) coarse_mass = sum(p.value for p in out.values()) selected = out[8, 3, 8] item = dict(case=name, pulse=pulse, hypothesis=hypothesis, initial_leaf_weight=initial, coarse_leaf_weight=coarse_mass, fine_leaf_weight=fine_mass, total_leaf_weight=coarse_mass+fine_mass, residual=coarse_mass+fine_mass-initial, inspected_slot=[8, 3, 8], selected_writer=selected.operation, inspected_value=selected.value, final_nonzero_traces=[trace(p) for p in out.values() if p.value]) results.append(item) for node in out.values(): if node.value: rows.append((name, hypothesis, node.phase, *node.slot, node.operation, node.value, ';'.join(f'{p.phase}:{p.slot}*{w}' for p, w in node.parents))) print(f'{name:20s} {hypothesis:27s} initial={initial:g} coarse={coarse_mass:g} ' f'fine={fine_mass:g} residual={item["residual"]:+g}; ' f'K(3,8),q8={selected.value:g} ({selected.operation})') sources = ['src/CelerisLab/lbm/refinement.py', 'src/CelerisLab/lbm/refinement_stepper.py', 'src/CelerisLab/lbm/kernels/refinement.cu', 'src/CelerisLab/lbm/kernels/boundary/bounce_back.cuh'] report = dict(scope='Independent single-interval linear packet/basis analysis; no collision or solver execution', geometry=dict(coarse=[16, 16], patch=[4, 4, 12, 12], fine=[24, 24], fine_origin=[2, 2], coarse_dx_dt=[1, 1], fine_dx_dt=[.5, .5], walls_Y=[8, 15]), assumptions=['fluid active populations pass unchanged between fine hops (identity transfer probe)', 'fine fluid inner ghosts reflect, never collide; outer halo output is invalid', 'solid destinations omitted; no filtering by coarse source in geometric LINKS', 'coalescence is equal-weight average of four children of each coarse target', 'results test these proposed extensions, not current production support or external libraries'], prestream_vs_postpull='Exact values and validity match on both hops for all three probes', source_files_read_only={p: hashlib.sha256((ROOT/p).read_bytes()).hexdigest() for p in sources}, script_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), results=results) (OUT/'results.json').write_text(json.dumps(report, indent=2)+'\n') with (OUT/'sources.csv').open('w', newline='') as stream: writer = csv.writer(stream) writer.writerow(('case', 'hypothesis', 'phase', 'q', 'x', 'y', 'operation', 'value', 'immediate_sources')) writer.writerows(rows) print('Prestream/postpull equivalence, valid coalescence reads, and unique destination writes: PASS') print(f'peak_rss_MiB={resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024:.3f}') if __name__ == '__main__': main()