511 lines
27 KiB
Markdown
511 lines
27 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.
|