607 lines
33 KiB
Markdown
607 lines
33 KiB
Markdown
# Periodic 2D Taylor–Green AMR campaign (prepared, not GPU-qualified)
|
||
|
||
This validation harness complements DFG Re100 and Jet/body tests. It measures
|
||
smooth 2D periodic decay and errors crossing fixed refinement interfaces at
|
||
Re_L=100 and 1000. It does **not** certify 3D turbulence, LES, Jet performance,
|
||
wall conditions, dynamic refinement or general high-Re flows.
|
||
|
||
## Reference and conventions
|
||
|
||
Primary implementation-author documentation, checked 2026-10-18:
|
||
- TensorMesh, exact velocity and pressure with a consistent phase:
|
||
https://docs.tensor-mesh.com/example_gallery/fluid/taylor_green.html
|
||
- AeroSim Nassu, 2D decay, energy and lattice-length Re definition:
|
||
https://docs.aerosim.io/nassu/validation/analytical/04_taylor_green_vortex_2d/README.html
|
||
|
||
We use the TensorMesh phase, rescaled to length L=N root cells:
|
||
|
||
k = 2*pi/L; A(t) = U*exp(-2*nu*k*k*t)
|
||
ux = -A*cos(k*x)*sin(k*y)
|
||
uy = A*sin(k*x)*cos(k*y)
|
||
p/rho0 = -A*A/4 * (cos(2*k*x)+cos(2*k*y))
|
||
E = <|u|^2>/2 = U*U/4 * exp(-4*nu*k*k*t)
|
||
|
||
Pressure is kinematic, with rho0=1. A global velocity sign reversal leaves
|
||
pressure unchanged; exchanging sine/cosine without the corresponding pressure
|
||
phase can reverse its sign. CPU tests independently check momentum residuals.
|
||
The nonlinear acceleration is a pressure gradient, **not zero**; the AeroSim
|
||
page's prose calling advection zero is not adopted. Do not mix phase variants
|
||
from different references. The formulas above are verified by substitution,
|
||
not by trusting a copied pressure expression.
|
||
|
||
Re_L=U*L/nu, not Re_k=U/(nu*k)=Re_L/(2*pi). U=.03 in lattice units,
|
||
Ma=U/cs=.0519615, cs^2=1/3, nu_root=.03*N/Re_L. Acoustic refinement uses
|
||
h_l=dt_l=2^-l: lattice velocity stays U, nu_l=2^l*nu_root and
|
||
tau_l=.5+3*nu_l. The worst root tau is .50288 (N32/Re1000), omega=1.98855,
|
||
inside the existing config guard. No viscosity clamping or guard override.
|
||
|
||
All initial arrays are physical FP64 equilibrium populations, supplied to the
|
||
public shifted-FP32 postcollision-G initializer. rho=1+3p at each true cell
|
||
center. These are valid equilibrium postcollision states, but do not include
|
||
Chapman–Enskog nonequilibrium stress; startup acoustic/kinetic error remains in
|
||
the measurements and is shared with uniform baselines. The incompressible
|
||
reference is not an exact finite-Mach LBM solution. This is why resolution alone
|
||
need not remove the full error floor.
|
||
|
||
## Geometry and workload
|
||
|
||
All patches use level-wide union form, so origins are zero, including fine
|
||
arrays with holes. Coordinates are (index+.5)*2^-level. Metrics integrate only
|
||
ACTIVE leaves, each weighted by 4^-level. Covered cells and halo cells never
|
||
enter norms or mass. Geometry tests prove exact single coverage at root-cell
|
||
resolution. All blocks are 8x8, and both root dimensions are periodic.
|
||
|
||
At each root N=32,64:
|
||
- 2 levels: L1 rectangle (N/8,N/8,7N/8,3N/4), in L0 indices.
|
||
- 3 levels: same L1 plus L2 rectangle (3N/4,N/2,3N/2,5N/4), in L1 indices.
|
||
|
||
These off-axis boundaries cross nonzero flow and gradients rather than sitting
|
||
only on symmetry or stagnation lines. Whole geometry scales with N.
|
||
|
||
16 cases: at each Re, uniform N=32,64,128,256 plus AMR (root32/root64)x(depth2/depth3).
|
||
Each AMR case therefore has both a same-root uniform baseline and a uniform
|
||
baseline at its finest spacing. Uniform N is its own lattice length, so nu and
|
||
step count are scaled to represent the same nondimensional solution.
|
||
Samples t*=tU/L = 0,.12,.24,.36,.48. End time is 16*N base steps, a meaningful
|
||
.48 domain turnover or 3.016 vortex-scale turnover times (scale 1/k).
|
||
At Re1000 energy decays about 7.3%; at Re100 about 53.1%. No plots or full fields;
|
||
each case writes five diagnostic rows and provenance, incrementally.
|
||
|
||
## Running (GPU owner must schedule launches)
|
||
|
||
CPU checks, from the repository root:
|
||
|
||
PYTHONPATH=src python -m unittest discover -s tests/validation/taylor_green -p 'test_*.py' -v
|
||
|
||
One GPU case, on the scheduled worker after checking occupancy:
|
||
|
||
CUDA_VISIBLE_DEVICES=<physical-id> python tests/validation/taylor_green/run_case.py --repo /path/to/reviewed/checkout --re 100 --n 32 --depth 1 --output output/taylor_green/re100_n32_d1.json
|
||
|
||
Depth 1 is uniform. Run uniform cases before AMR for each Re; inspect baseline
|
||
screening failures before proceeding. For a complete matrix, repeat the uniform
|
||
call with N=32,64,128,256 and AMR calls with N=32,64 / depth=2,3, at each Re.
|
||
Use serial process startup on the parent's assigned Horsea GPUs. This harness
|
||
does not schedule or acquire GPUs. No GPU was used during preparation.
|
||
|
||
python tests/validation/taylor_green/assess.py output/taylor_green/re*_n*_d*.json --output output/taylor_green/assessment.json
|
||
|
||
The local API/geometry review used clean staging commit
|
||
cd3a657f9d3833e812c3cca173525f165b48710a. This is **not** a claim of results on d79
|
||
or any historical commit. Each runtime output records actual Git HEAD/dirty
|
||
state, an aggregate source-tree hash, plus SHA256 of all harness Python files. Assessment refuses dirty checkouts and mixed source
|
||
or harness identities. Keep reports outside the checkout or .gitignore them so
|
||
new outputs do not change its dirty flag between cases. The source-tree hash excludes bytecode caches; production qualification requires
|
||
a clean checkout.
|
||
The runner uses the existing PeriodicBlockStepper / FixedPatchStepper periodic
|
||
paths only. It does not depend on the new channel-root implementation.
|
||
|
||
## Preregistered assessment, before any GPU results
|
||
|
||
All sampled times must satisfy finite screening ceilings:
|
||
- Relative composite velocity L2 <= 5%
|
||
- Relative globally gauge-adjusted pressure L2 <= 15%
|
||
- Relative kinetic-energy error <= 5%
|
||
- Composite mass drift from downloaded t0 <= 1e-5
|
||
|
||
These are screening budgets, not literature-certified tolerances. Acceptance
|
||
also requires all 16 cases, common source/harness, correct nondimensional times
|
||
and viscosity, and baseline-relative checks on worst post-startup-sample errors:
|
||
- AMR error <= max(2 * same-root uniform error, declared numerical floor).
|
||
- Root64 AMR error <= max(.9 * root32 AMR error, floor), for each depth/Re.
|
||
- Uniform256 error <= max(.9 * uniform32 error, floor).
|
||
|
||
Floors: velocity .002, pressure .02, energy .004. They are declared low-Mach /
|
||
equilibrium-startup budgets, not fitted to observed results. Ma^2=.0027 motivates
|
||
their scale; it is an asymptotic expectation, not a proof of those coefficients.
|
||
The coarse baseline sets the AMR budget because much of the domain remains
|
||
coarse. The finest uniform error and AMR/fine ratio are always reported, with no
|
||
claim that partial refinement should match a fully fine domain. A pass below a
|
||
floor is bounded accuracy, not a measured convergence order. Report errors and
|
||
ratios even for a pass. Failure requires diagnosis or a separately preregistered
|
||
follow-up, never retroactive tolerance tuning. Higher Re is deliberately absent;
|
||
Re100/1000 must first be stable, resolved and reviewed.
|
||
|
||
Diagnostics use one global pressure gauge, direct cell-center analytic values,
|
||
kinetic energy per unit reference mass, and actual leaf cell areas. Composite
|
||
midpoint quadrature introduces a small initial energy integration error, retained
|
||
rather than subtracted. Mass drift is relative to downloaded t0, so density
|
||
initialization and mixed-grid quadrature do not masquerade as time drift.
|
||
|
||
## Pilot scheduling and transfer-consistency scope
|
||
|
||
Start with one uniform case and one matched AMR case; the 16-case matrix is a
|
||
qualification plan, not authorization to launch every case automatically. The
|
||
GPU owner reviews the pilot before expanding it. Each process prints a flushed
|
||
READY only after initialization, a real base step exercising every level's
|
||
kernel/halo/transfer path, and a finite positive-density download check. That
|
||
step belongs to the measured trajectory; it is not discarded warmup. PROGRESS
|
||
messages contain each of the five diagnostic samples. READY alone is not an
|
||
accuracy pass. Reports include per-level active cells, hops and collision updates.
|
||
|
||
The complete matrix costs 768,540,672 active collision updates and 21,504 root
|
||
intervals, excluding ghost streaming, halos, transfers and diagnostic work.
|
||
Uniform N256 is the largest case (268,435,456 updates / 4096 intervals per Re).
|
||
AMR N64/depth3 needs 50,987,008 updates / 1024 intervals. These are work counts,
|
||
not GPU wall-time estimates. Baseline comparisons remain available on failed
|
||
screens and partial pilots; absent/nonfinite operands are null, never passing.
|
||
|
||
Acoustic viscosity scaling and unchanged lattice velocity do not by themselves
|
||
prove nonequilibrium-stress consistency across refinement interfaces. A smooth
|
||
collocated Chapman–Enskog postcollision nonequilibrium has a (tau-1)*h factor;
|
||
the existing implementation instead uses volumetric piecewise-constant explosion
|
||
and stream-only ghosts. Whether that actual transfer construction achieves the
|
||
needed stress accuracy is an unresolved question for this pilot to measure.
|
||
It is not a proven defect, and a collocated-state scaling factor must not be
|
||
inserted into this different transfer operator without a separate derivation
|
||
and validation. This campaign measures the current operator and makes no
|
||
theoretical stress-consistency certification or production-kernel change.
|
||
|
||
## Repository integration
|
||
|
||
The four Python harness files remain together under tests/validation/taylor_green, so runtime provenance hashes precisely this harness directory. Formatting changes produce a new harness identity; preparation and integrated receipts must not be mixed. All analytic definitions, numerical floors, assessment gates, sample times, and source-import assertions are unchanged. Production source is unchanged from the cd3 snapshot; these periodic tests do not waive the separate channel GPU gate.
|
||
|
||
## Oblique shear wave (test-only diagnostic, not GPU-qualified)
|
||
|
||
`shear_wave.py` reuses the frozen oracle's constants, cell centers and
|
||
geometry. `oracle.py` is byte-identical, and `test_shear_wave.py` pins its
|
||
eec4677 SHA-256. `run_case.py --flow shear_wave` selects the shear wave;
|
||
the default flow and its receipt are the unchanged Taylor–Green path.
|
||
|
||
### Convention
|
||
|
||
Integer mode (2,1) on the L=N periodic root domain:
|
||
- the wavevector `k = (2*pi/L)*(2,1)` points 26.565° from +x;
|
||
- mode (1,2) would point 63.435°, and a wrong-mode test catches a swap.
|
||
|
||
Polarization is `E = (-1,2)/sqrt(5)`, perpendicular to k:
|
||
|
||
u = U*E*sin(k.x + phi)*exp(-nu*|k|^2*t), phi = 0, p = const, rho0 = 1
|
||
|
||
`nu = U*N/100`, the Taylor–Green Re100 viscosity at the same N. This is an
|
||
exact incompressible Navier–Stokes solution. The initial condition is FP64
|
||
second-order equilibrium at the actual leaf centers, with no
|
||
non-equilibrium part.
|
||
|
||
### Physical caveats
|
||
|
||
1. *Scope of the cubic-term argument.* The second-order D2Q9 equilibrium
|
||
lacks the cubic third moment `rho*u_a*u_b*u_g` of the Maxwellian (Dellar,
|
||
https://people.maths.ox.ac.uk/dellar/papers/Galilean.pdf, eq. 3). At
|
||
Navier–Stokes order this produces a stress error proportional to
|
||
`d_g(rho u_a u_b u_g)`.
|
||
|
||
For the ideal constant-density, zero-background transverse wave, k.E = 0
|
||
makes that contracted derivative vanish. That is the only claim made.
|
||
It does not remove other discrete or finite-Mach errors. It is not
|
||
guaranteed once AMR introduces density, longitudinal or higher-mode
|
||
contamination. The analytic NS field itself is exact.
|
||
2. *Startup.* Equilibrium initialization is not the discrete shear
|
||
eigenmode (Mei et al., https://doi.org/10.1016/j.compfluid.2005.08.008).
|
||
- The decay rate is a free-intercept least-squares fit of ln R over the
|
||
samples with t* >= 0.12, where `R = hypot(a_hat, b_hat)`.
|
||
- The intercept cancels only a constant amplitude prefactor, and only
|
||
once a single exponential dominates.
|
||
- Per-interval rates and the maximum log-fit residual are kept, so a
|
||
lingering transient stays visible.
|
||
- Late sampling alone does not show that transients have gone.
|
||
|
||
### Metrics
|
||
|
||
Computed on ACTIVE leaf cells, each weighted by its area `4**-level` in
|
||
root-cell units. The partition must cover the domain exactly once, and one
|
||
global pressure gauge is used.
|
||
|
||
- `a_hat`, `b_hat`: weighted least-squares fit of `u.E` onto sin/cos, using
|
||
the 2x2 Gram matrix of the actual composite quadrature. A wrong Fourier
|
||
mode need not project to exactly zero on this quadrature.
|
||
- `amplitude_error = R/A_exact - 1`.
|
||
- `phase_drift = atan2(b_hat, a_hat)`, in radians, reported separately.
|
||
- Rates are positive (minus the fitted slope).
|
||
- Per root step they are compared with `nu*|k|^2`. Uniform 2N uses its
|
||
own `nu = 0.0768` at N=256 and doubled step counts.
|
||
- In t* they are compared with `5*(2*pi)^2/Re = 1.97392088`.
|
||
- `rate_error = |rate/exact - 1|`.
|
||
- `velocity_l2`, `residual_l2` (velocity left after removing the fitted
|
||
mode) and `longitudinal_l2` (the `u.k_hat` part), all relative to the
|
||
exact-field norm. A longitudinal perturbation also raises the
|
||
full-vector residual and the velocity L2.
|
||
- `spurious_pressure_rms`: the raw gauged rms of `p = (rho-1)/3`.
|
||
- `spurious_pressure_scaled`: that rms divided by `A_exact(t)^2/4`, a
|
||
continuum reference scale. It is *not* the discrete, globally gauged
|
||
Taylor–Green norm on the composite grid. Exact pressure is constant, so
|
||
no relative-to-exact claim is made. Max and per-level values are kept.
|
||
|
||
### Preregistered screens (`shear_wave.assess`)
|
||
|
||
Run set: uniform N, uniform 2N, and refined depth-2 runs at root N.
|
||
|
||
- `eps(N) = (|k| h_root)^2 = 5*(2*pi/N)^2`: dimensionless, coefficient
|
||
one, 0.01205 at N=128. This is a chosen screen, not a proven error bound.
|
||
- Absolute screens:
|
||
- rate_error, max |phase_drift| (radians) and max residual_l2 must each
|
||
be <= eps;
|
||
- velocity_l2 <= 0.05, mass <= 1e-5, spurious_pressure_scaled <= 0.02.
|
||
- Budgets keep the `assess.py` form, `refined <= max(2*control_N, floor)`:
|
||
- floors are 0.002 for rate and residual, 0.02 for pressure;
|
||
- the comparative pressure budget is always redundant:
|
||
`max(2*control, 0.02)` is never below the 0.02 absolute ceiling;
|
||
- raw ratios to both the root and finest controls, including raw
|
||
pressure rms, are always reported.
|
||
- Every record is validated before any screen is applied:
|
||
- exact scheduled steps and t*, with no duplicates;
|
||
- every numeric field finite, including list fields and density;
|
||
- error quantities nonnegative and rho_min > 0;
|
||
- signed quantities (amplitudes, `amplitude_error`, `phase_drift`,
|
||
per-interval rate errors) keep their sign.
|
||
- Outcomes are kept distinct:
|
||
- INVALID_CONTROL: a control or refined run is missing, a control is
|
||
incomplete or invalid, or the records come from mixed sources;
|
||
- INVALID_RUN: a refined record fails validation;
|
||
- CONTROL_SCREEN_FAIL: complete, valid controls fail their own screens.
|
||
Each refined run's `own_screens_pass` is still reported, but
|
||
`controlled_pass` is false, so it is never a controlled-comparison pass;
|
||
- PASS/FAIL: every refined run's `controlled_pass` (own screens and
|
||
budgets against valid, passing controls).
|
||
- Finite modal extinction (late R = 0) is a physical failure, not
|
||
malformed data. The run gets `rate_fit_valid=false` with null fit
|
||
quantities, and its other metrics are kept. Nothing is clipped and no
|
||
rate is invented. The result is CONTROL_SCREEN_FAIL for a control, or
|
||
FAIL for a refined run.
|
||
- Screens are never retuned.
|
||
|
||
### Limitations
|
||
|
||
One flow, one phase and one rectangle, SRT only. The rectangle's vertical
|
||
faces span 0.625 tangential periods and its horizontal faces 1.5, so this
|
||
is not placement robustness. Two resolutions show a trend, not an order.
|
||
|
||
### Receipt assessment and runner integrity
|
||
|
||
- Fixed four-case N128 contract:
|
||
`python assess_shear_wave.py U128.json U256.json R128_constant.json R128_projected.json --output report.json --expected-revision <sha>`.
|
||
It reuses the shared provenance, build, workload and sample-time checks
|
||
from `assess_projected_pairs.py`, and adds shear metadata checks (flow,
|
||
mode, polarization, angle, phase, eps, limits, disabled early trace, and
|
||
pinned `shear_wave.py` hash).
|
||
- Missing, extra, duplicate or mixed-source records give `INVALID_SET`,
|
||
as does any failed shared check.
|
||
- Otherwise the result comes from `shear_wave.assess`, which separates
|
||
`INVALID_CONTROL` from `CONTROL_SCREEN_FAIL`.
|
||
- `run_case.verify_source(..., flow="shear_wave")` requires the imported
|
||
`shear_wave.py` to be the selected harness file with the pinned
|
||
`SHEAR_WAVE_SHA256`. The default TG flow does not import it.
|
||
- Sample and READY finiteness use `finite_row`, which accepts scalar and
|
||
list diagnostics. For TG's all-scalar rows it behaves the same as before.
|
||
- Merge note: native 92b8afe adds a `scaled_n256` receipt block. When the
|
||
two are merged, keep both blocks and make `--flow shear_wave` and
|
||
`scaled_n256` mutually exclusive. Not merged here.
|
||
|
||
### Scaled shear diagnostic (opt-in `scaled_shear_n256`)
|
||
|
||
Runner: `run_case.py --flow shear_wave --diagnostic scaled_shear_n256 --re 100`
|
||
with one of these four cases:
|
||
- `--n 256 --depth 1` (U256)
|
||
- `--n 512 --depth 1` (U512)
|
||
- `--n 256 --depth 2 --explosion constant` (constant R256)
|
||
- `--n 256 --depth 2 --explosion projected_linear` (projected R256)
|
||
|
||
Everything physical is unchanged from N128:
|
||
- `rectangles(256,2)` covers the same physical box;
|
||
- same t* schedule (16N root steps);
|
||
- `nu = U*N/100`;
|
||
- same `eps(N)`, limits and floors.
|
||
|
||
`scaled_n256` (Taylor–Green, from native 92b8afe) and `scaled_shear_n256`
|
||
each require their own flow, so they are mutually exclusive. N512 is
|
||
accepted only through one of the two diagnostics. The shear diagnostic
|
||
takes no early-pressure trace.
|
||
|
||
Assessment:
|
||
|
||
python assess_shear_wave.py U256.json U512.json R256_constant.json R256_projected.json \
|
||
--diagnostic scaled_shear_n256 --reference-files <four de5b0cc N128 receipts> \
|
||
--output report.json --expected-revision <sha>
|
||
|
||
- The scaled N256/512 case, build and workload checks come from the
|
||
92b8afe assessor. Its TG-only diagnostic identity and early-sampling
|
||
checks are not used. Instead every record must carry
|
||
`diagnostic=scaled_shear_n256`, and N128 records must carry none.
|
||
- The reference N128 receipts are hash-pinned to the audited de5b0cc
|
||
evidence (commit cba6bca). They are never relabelled as fresh controls.
|
||
- The report always includes, for each case:
|
||
- the raw signed rate bias `rate/exact - 1` and the interval errors;
|
||
- each refined run's signed excess over *each* uniform control (rate
|
||
bias, residual, raw pressure rms);
|
||
- the N128→N256 signed changes and ratios. The ratio is null when the
|
||
N128 value is zero.
|
||
- These are descriptive. Passing or failing another floor-controlled
|
||
screen is not the conclusion, and a two-resolution ratio is not a
|
||
convergence order.
|
||
- Portability: the receipt's recomputed `eps = |k|^2` is compared within
|
||
4 ULPs (`close_ulps`), not by exact equality. A cross-runtime replay
|
||
differed by one ULP: 0.012047856934923534 on Horsea vs
|
||
0.012047856934923532 elsewhere. Source and file hashes, case identity,
|
||
the other metadata and every scientific threshold stay exact.
|
||
|
||
### Nested shear preset (opt-in `nested_shear_n128`)
|
||
|
||
A fixed three-level, two-region preset, defined in `shear_nested.py`. The
|
||
wave, phase, Re100/U=0.03, initialization, five sample times, eps(root N),
|
||
limits and floors are the same as before.
|
||
|
||
- Refinements, given as parent-frame `(x0, y0, x1, y1)` rectangles on
|
||
level-wide, zero-origin unions:
|
||
- L0→L1: `(16,16,60,112)`, `(68,24,112,120)`
|
||
- L1→L2: `(44,44,108,212)`, `(148,60,212,228)`
|
||
- Leaves `[7936, 12288, 86016]`, hops `[2048, 4096, 8192]`, work
|
||
771227648 per refined case; 3723493376 for all four cases.
|
||
- Level ν `[.0384, .0768, .1536]`, τ `[.6152, .7304, .9608]`.
|
||
|
||
Cases (`run_case.py --flow shear_wave --diagnostic nested_shear_n128 --re 100`):
|
||
- `--n 128 --depth 1`
|
||
- `--n 512 --depth 1` — the finest control is 4N, not 2N
|
||
- `--n 128 --depth 3`
|
||
- `--n 128 --depth 3 --explosion projected_linear [--final-snapshot]`
|
||
|
||
`--final-snapshot` is allowed only for the projected depth-3 case. It writes
|
||
`<output>.final_macro.npz`, containing:
|
||
- ACTIVE leaves packed as `level`/`i`/`j`;
|
||
- `rho`, `ux`, `uy` from the FP64 physical populations at the final root
|
||
synchronization;
|
||
- embedded metadata: exact time, phase, mode and config.
|
||
|
||
It contains no populations, restart state or time series. Its SHA-256 and
|
||
size go into the receipt. A file over 8 MiB is removed and reported, never
|
||
kept. All old paths stay scalar-only.
|
||
|
||
Assessment: `assess_shear_wave.py U128.json U512.json R128c.json R128p.json
|
||
--diagnostic nested_shear_n128 --output report.json --expected-revision <sha>`.
|
||
- It reuses the case-agnostic provenance checks from the TG assessor, plus
|
||
exact nested scales, builds, patch, workload, metadata and the pinned
|
||
`shear_nested.py` hash.
|
||
- The physics is `shear_wave.assess` generalized only in its depth-3 / 4N
|
||
shape contract; the metrics are unchanged.
|
||
- `shear_wave.py` is byte-identical (81d5c8ee…), so historical receipt
|
||
identities and verdicts are untouched.
|
||
- This preset changes placement and refined volume as well as depth. It
|
||
gives no isolated cost of an extra level and no resolution trend.
|
||
|
||
### Depth-2 twin of the nested preset (opt-in `twin_shear_n128`)
|
||
|
||
`shear_twin.py` uses the same two L0→L1 boxes as `shear_nested.py`, with no
|
||
L2. Leaves are `[7936, 33792]`, hops `[2048, 4096]`, and work is 154664960 per
|
||
refined case (611319808 for all four).
|
||
|
||
The campaign is four fresh runs:
|
||
`run_case.py --flow shear_wave --diagnostic twin_shear_n128 --re 100` with
|
||
- `--n 128 --depth 1`
|
||
- `--n 256 --depth 1` (the finest control is 2N)
|
||
- `--n 128 --depth 2`
|
||
- `--n 128 --depth 2 --explosion projected_linear`
|
||
|
||
There is no snapshot option. Older exact controls serve only as consistency
|
||
checks; they are not reused as references.
|
||
|
||
Assessment uses the same preset contract as the nested preset, through
|
||
`assess_shear_wave.py ... --diagnostic twin_shear_n128`:
|
||
- the physics is the unchanged depth-2 / 2N `shear_wave.assess`;
|
||
- receipts must pin `shear_twin.py`, `shear_nested.py` and `shear_wave.py`;
|
||
- `shear_nested.py` stays byte-identical (fa6cfe87…), so the 335624c nested
|
||
receipts still validate.
|
||
|
||
Labels:
|
||
- *Twin vs nested* is the effect of adding this nested L2 refinement.
|
||
Removing L2 also changes the finest spacing and refined volume, so it does
|
||
not isolate abstract depth.
|
||
- *Twin vs the single-box depth-2 runs* is a placement/geometry contrast at
|
||
equal depth.
|
||
- Neither contrast is additive by construction.
|
||
- The thin-band/acoustic explanation for the nested L1 pressure is a
|
||
hypothesis, not established.
|
||
|
||
### Signed interface-probe traces (opt-in `--probe-trace`, mechanism diagnostic)
|
||
|
||
`shear_probes.py` (pinned) uses native's validated 24-target layout through
|
||
box 1, in root-128 physical coordinates:
|
||
- a horizontal line y = 56, crossing the vertical faces x = 16 and 22;
|
||
- a vertical line x = 38, crossing the horizontal faces y = 16 and 22;
|
||
- normal coordinates 12.5, 14.5, 15.5, 16.25, 17.25, 19.25, 20.75, 21.75,
|
||
22.125, 23.125, 24.125, 26.125.
|
||
|
||
Each target maps to the nearest ACTIVE leaf center. The deterministic tie
|
||
rule is: distance, then finer level, then smaller j, then smaller i. This
|
||
gives 24 unique cells in every case, and nested has 3 L0 + 5 L1 + 4 L2 per
|
||
transect. Maximum displacement from target to center is 0.625 root cells in
|
||
U128 (0.177 in U512).
|
||
|
||
Allowed cases:
|
||
- nested U128, nested U512, nested projected depth 3;
|
||
- twin projected depth 2.
|
||
|
||
The option can't be combined with `--final-snapshot`.
|
||
|
||
Sampling:
|
||
- The receipt stores each probe's leaf level, `i`/`j`, actual cell center
|
||
and displacement from its target, all in root-physical units (N=128).
|
||
- Grids differ between cases, so centers are *not* collocated. Analytic
|
||
fields are evaluated at each actual center (`shear_probes.residuals`), and
|
||
comparisons across cases are between residuals at nearby but distinct
|
||
centers.
|
||
- Times are root-physical steps 0–128 and 1920–2048. U512 is sampled every 4
|
||
lattice steps to match.
|
||
- Each sample stores `rho`, `ux`, `uy` from the FP64 physical populations,
|
||
POST-collision G at root synchronization only. No substep content is
|
||
observed, and grid-scale alternation can alias.
|
||
|
||
What's kept and enforced:
|
||
- The five qualification samples stay unchanged.
|
||
- No field dumps. The trace is validated for exact schedule, finiteness and
|
||
a 600 kB cap. If invalid it is dropped and an error is recorded, keeping
|
||
the scalar receipt.
|
||
- There are no new pass gates; this is a mechanism diagnostic only.
|
||
|
||
### Single x-gap-width contrast (`wide_x_shear_n128`)
|
||
|
||
This opt-in admits only Re100/N128/projected depth3 with `--probe-trace`.
|
||
The outer boxes, three grid spacings, viscosities, initialization, five main
|
||
sample times and trace windows are unchanged. L1→L2 parent-frame rectangles
|
||
are `[(56,44,96,212),(160,60,200,228)]`: both x-normal middle gaps widen from
|
||
6 to 12 root cells, while y gaps remain 6. Active leaves are
|
||
`[7936,20352,53760]`, hops `[2048,4096,8192]`, work 540,016,640 active updates.
|
||
This also moves the L2 x faces and reduces its volume; it is not a pure
|
||
travel-distance experiment. No new qualification matrix, assessor, threshold
|
||
or snapshot is added. Existing scalar screens and all failures stay visible.
|
||
|
||
The same 24 targets and actual-center metadata are retained. The horizontal
|
||
probes stop before the new inner face x = 28: they do not bracket that interface
|
||
or sample its fine side. The first 8 horizontal L0/L1 probes keep identical
|
||
centers, and the y-normal x = 38 transect is unchanged. Their temporal residuals
|
||
can support a descriptive timing contrast, but cannot establish a crossing
|
||
or reflection coefficient. Changed-level probes must not be treated as
|
||
collocated samples. `rho-1` remains raw density deviation; do not substitute
|
||
the 24-probe mean for the global pressure gauge.
|
||
|
||
### POST-G initialization counterfactual (`postg_shear_n128`)
|
||
|
||
Exactly three fresh Re100 cases are admitted: U128, U512, and projected R128
|
||
depth 3 with the original nested rectangles. Each requires `--flow shear_wave
|
||
--diagnostic postg_shear_n128 --probe-trace`; snapshots and early-pressure mode
|
||
are excluded. Geometry, physical velocity/density, viscosities, collisions,
|
||
five main times and the 24 signed probes/windows are unchanged. Total work is
|
||
2,952,265,728 active updates, with 15 main rows, 774 trace rows and five builds.
|
||
|
||
Only initialization changes. At level spacing h, k_level = h k and
|
||
A_i = 3 w_i U cos(theta) (c_i dot e) (c_i dot k_level). Initialize physical
|
||
FP64 **POST G = feq - (tau - 1) A**, then use the existing shifted FP32 codec.
|
||
This is the first-gradient, low-Mach Chapman-Enskog approximation, not an
|
||
exact discrete eigenstate. The PRE coefficient is -tau; the physical viscous
|
||
stress coefficient tau - 1/2 must not replace the raw POST-G coefficient.
|
||
The correction has zero mass/momentum before encoding; FP32 introduces normal
|
||
roundoff. U512 uses its native k and tau, matching nested L2 physical spacing.
|
||
|
||
Receipts pin the new initializer module and identify `postg_first_gradient_v1`,
|
||
with `qualification_eligible=false`. Existing scalar screens remain visible
|
||
as descriptive outcomes, including failures; no new pass gate or assessor is
|
||
introduced. Historical assessors reject the new diagnostic and initialization
|
||
identities. Compare raw rows and signed traces with the retained equilibrium
|
||
receipts as a startup-state counterfactual. The host first-interval pressure
|
||
RMS reduction is not a prediction of long-time improvement, and individual
|
||
probe errors can increase. All equilibrium paths and historical verdicts stay
|
||
unchanged.
|
||
|
||
### Short square orientation diagnostic (`axis_square_shear_n128`)
|
||
|
||
Four fresh cases only: U128, U256, constant R128 and projected R128 depth 2.
|
||
Use `--flow shear_wave --diagnostic axis_square_shear_n128 --probe-trace`.
|
||
The supported union is `[[(32,32,96,96)]]`; a full-height periodic fine strip
|
||
is not supported by the unchanged production geometry. All four cases use
|
||
POST G = feq - (tau - 1) A, mode (2,0), polarization (0,1), phase pi/4,
|
||
U=.03 and Re100. Root/fine nu are .0384/.0768 and tau are .6152/.7304.
|
||
This first-gradient low-Mach initialization is not an exact discrete mode.
|
||
|
||
Stop at root step 8: two global rows at 0/8, nine local rows at 0..8;
|
||
U256 advances two native steps per root step. Refined leaves are [12288,16384],
|
||
hops [8,16], work 360,448 per refined case. Four-case work is 1,900,544 ACTIVE
|
||
updates, six build sidecars and 720 native cell-time samples. Existing runtime,
|
||
build/source guards and receipt/trace caps apply. No snapshots or late fit.
|
||
`screening_pass=null`, `qualification_eligible=false`: exit zero means valid
|
||
finite completion, with no physical pass threshold or legacy assessor.
|
||
|
||
Eight root-unit-cell groups (i,j): inner L/R/B/T = (32,64)/(95,63)/(64,32)/(63,95),
|
||
outer L/R/B/T = (31,64)/(96,63)/(64,31)/(63,96). Refined inner groups contain four
|
||
fine cells, outer groups one coarse cell; U128 uses one and U256 four per group.
|
||
Retain raw rho/ux/uy, native indices, physical centers/areas and parity. Group
|
||
residuals are signed means of rho-1 and rho*u-u_exact, evaluated at each actual
|
||
center; normalization uses that group's mean analytic d(uy)/dx. Only inner
|
||
L/B and R/T pairs have exactly opposite equal-magnitude gradients. Controls
|
||
have their own native quadrature. Probe density is ungauged; global pressure
|
||
RMS uses one domain gauge.
|
||
|
||
Actual-table local corridors match tangentially extended straight faces beyond
|
||
22.5 root cells. The conservative paired-map radius is 2.5 root cells per root
|
||
step, so these selected groups through step 8 are locally straight-face
|
||
equivalent. This is not a claim about global corner errors. For projected
|
||
explosion with actual missing-normal-gradient fallback, the stationary
|
||
linearized affine reference after the first complete root interval predicts
|
||
zero conserved-moment error on vertical faces. At the
|
||
bottom/top inner fine quartets its mean delta jx / d(uy)/dx is
|
||
-/+ 1/(576*tau_f), with opposite adjacent-coarse redistribution.
|
||
Keep raw values, step-zero rounding and fresh controls: sinusoidal curvature
|
||
and finite-Mach effects prevent treating this coefficient as an exact gate.
|
||
|
||
### Test-only centered straight-face comparison
|
||
|
||
`centered_face_square_n128` reuses the square axis-wave POST-G initializer,
|
||
geometry, native probes and root steps 0–8. It has four fresh cases: U128,
|
||
U256, current projected R128, and experimental centered R128. This is a
|
||
qualification-ineligible diagnostic; there is no legacy assessor or new physics gate.
|
||
|
||
Only the candidate's private generated fine-level `blocks.cu` changes. A
|
||
2,112-byte constant mask selects 1,792 rows (448 complete donor quartets).
|
||
The diagonal projected correction is doubled on straight faces with exactly
|
||
one unsupported normal axis and both legal tangent neighbors. Donor centers
|
||
within four root cells of a corner retain the current rule, as do all other
|
||
patterns, axial populations and rest. The mask is symmetric under transpose
|
||
and reflection. Its hash and the actual modified source/PTX hashes are retained;
|
||
production files, restrictions, collision, scheduling and launch arguments stay fixed.
|
||
A complete quartet has zero summed offset, so each population's quartet mean
|
||
is preserved. The perpendicular gradient also retains equal characteristic
|
||
packets; the existing two-hop conservation routing therefore remains applicable.
|
||
Host tests additionally check the mixed mask through complete two-hop/collision
|
||
cycles, including corner grazing, and execute the actual edited kernel via C++.
|
||
The central probes are more than 20 root cells from mask transitions; the
|
||
reviewed conservative dependency radius is 2.5 root cells per root interval.
|
||
|
||
The separate comparison subtracts each group's step-zero residual and the
|
||
fresh uniform control at matching quadrature (U256 inner, U128 outer). It retains
|
||
signed density and both momentum components, actual-center gradient normalization,
|
||
parities, and sign flips. Step 1 requires bottom-inner cross-momentum magnitude
|
||
improvement greater than its deadband, and top-inner nonworsening within it.
|
||
Each horizontal face's step-8 RMS combines its inner and outer group means;
|
||
both must be nonworse. All four vertical groups must remain unchanged within
|
||
the component deadbands at every sampled root step. The norm
|
||
`sqrt(drho²/3 + djx² + djy²)` must not worsen beyond its corresponding deadband.
|
||
Sampled raw-pressure envelope and step-8 global gauged pressure RMS must not
|
||
worsen beyond the pressure deadband. Nonfinite/nonpositive sampled density,
|
||
invalid traces, source/build mismatch, or exceeded observed population envelope
|
||
reject the comparison. A small top signal or sign reversal remains explicit.
|
||
|
||
The predeclared shifted population envelope is 1/32. From per-population oracle
|
||
allowance `6e-8 + 2e-7*1/32`, pairwise moment deadbands are
|
||
`[1.1925e-6, 7.95e-7, 7.95e-7]`; pressure uses the density deadband divided by 3.
|
||
Area averaging cannot enlarge this local allowance. These are practical diagnostic
|
||
deadbands, not certified accumulated root-8 rounding bounds. The envelope is
|
||
checked on downloaded synchronized ACTIVE populations, not hidden substeps.
|
||
Known quadratic fine-cell O(h) terms, corner transitions, repeated coupling and
|
||
stability remain unresolved. Passing permits review of a candidate, not promotion.
|
||
|
||
Run the existing `run_case.py` with `--diagnostic centered_face_square_n128
|
||
--flow shear_wave --re 100 --probe-trace --test-reconstruction current` for
|
||
U128/U256 (depth 1, constant) and current R128 (depth 2, projected_linear).
|
||
For candidate R128 use `--test-reconstruction centered_face_v1`. All require
|
||
an exact clean `--repo`, `--expected-revision`, fresh `--output`, and either
|
||
`--dry-run` or explicit single-device `--run-gpu`. Compare ordered receipts with
|
||
`shear_centered.py --repo REPO --expected-revision SHA --output comparison.json
|
||
U128.json U256.json current.json candidate.json`. Total work is 1,900,544 ACTIVE
|
||
updates, six build sidecars, and 720 cell-time samples; scalar cap stays 1 MiB/case.
|