Experimental aligned-box viscous step
This contract defines a bounded, opt-in, unforced viscous update
followed by a pressure proposal. The experiment lives in
experiments/aligned_stokes.rs, outside the production
library, and is invoked only by its example and tests. Its starting
source is 0e13b02294b247d9f59326f98e6233fb9280967e. It adds
a finite-step experiment; it does not qualify the older liquid transport
facade or a continuum solver. The current-main integration
milestone records selective provenance and adds an encircling-flow
acceptance fixture.
Domain and stored coefficients
Borrow one immutable AlignedStrain and its exact
geometry owner. Admission remains one retained internal grid-aligned box
with at least one full fluid cell of padding. The obstacle is stationary
and no-slip; the outer domain is sealed and free-slip. Use the existing
pressure-active face map, stored areas, wet-cell volumes and stored
positive face masses throughout. The object’s constant density and
dynamic viscosity supply the material values; both are strictly positive
under the current constructor. There is no second material parameter or
zero-viscosity override. A zero velocity state remains an admissible
identity with positive viscosity.
Caller velocities are full MAC arrays of binary64 values. Shapes must match; every outer or blocked face must be exactly zero. Inputs and used coefficients must be finite normal values or zero, with positive denominators. Before any proposal and again on the final candidate, enclose each wet cell’s actual integrated flux divided by its stored positive volume. Require
upper(abs(Q_i(u))/V_i) <= divergence_limit,
where the caller supplies a finite nonnegative limit in
1/s. Check all wet cells, including every pressure gauge
cell. Dry cells are excluded only by their explicit zero volume. Use one
shared oriented area per active face; the sealed component flux
cancellation is then an exact algebraic property of the incidence, not a
floating sum that happens to lie near zero.
The reconstructed strain
derivation fixes the normal rows with weight 2V,
engineering shear rows with actual represented fluid-quadrant weights,
reflected corner rows and eliminated stationary wall traces. Retain
included zero rows. Outer-wall shear is analytically eliminated by
sealed-normal and free-slip traces before edge enumeration. Treat the
stored binary64 coefficients and weights as exact real input numbers in
the following algebra; do not infer exact geometric products from their
rounded assembly.
Viscosity proposal and actual acceptance
Write M=diag(m_f), K=E^T W E, and
D0(u) = sum_r w_r (sum_f E_rf u_f)^2,
H(u) = sum_f m_f u_f^2 / 2.
The exact unforced explicit reference is
v=u-dt*mu*M^-1*K*u. The numerical proposal may round its
gather, transpose and update. A nearest-rounded row-bound diagnostic
does not authorize it. Independently enclose the bound from the actual
stored rows and masses:
L_r = sum_g abs(E_rg),
B = max_f [ (sum_r w_r abs(E_rf) L_r) / m_f ].
Require a finite nonnegative enclosing upper endpoint
B_upper and an outward upper bound on
dt*mu*B_upper at most 2, for a finite positive
requested dt. This supplies the exact-real Euler premise.
It does not control the rounding of the proposed velocity.
For the actual stored proposal v_hat, independently
enclose
DeltaH_visc = sum_f (m_f/2) (v_hat_f-u_f) (v_hat_f+u_f)
and require its upper endpoint to be at most zero. This factorized
difference is exactly H(v_hat)-H(u) for the represented
states. It avoids subtracting two separately enclosed, almost equal
energies. An overlapping sign enclosure is a refusal, not an energy
tolerance.
Energy decrease alone would permit an unrelated damping operation. Therefore also enclose each coordinate’s momentum equation defect and its dimensional scale:
e_visc_f = m_f (v_hat_f-u_f) + dt*mu*(K*u)_f,
C_f = sum_r abs(E_rf*w_r*(E*u)_r),
s_visc_f = abs(m_f (v_hat_f-u_f)) + dt*mu*C_f.
The caller supplies a finite dimensionless relative defect limit
0 <= tau_visc <= 1e-8. Require
upper(abs(e_visc_f)) <= lower(tau_visc*s_visc_f) for
every active face. The shared relative_update_limit sets
both defect limits; its default is 4096*f64::EPSILON. The
accepted binary64 maximum is 1e-8_f64.next_down(), the
largest representable value below the exact decimal cap; the nearest
1e-8 literal lies slightly above it. There is no absolute
floor. A provably zero defect and zero scale passes as an identity; an
unresolved zero-scale enclosure refuses. This is a quantified
approximate discrete equation, not a claim that the rounded proposal is
the exact Euler solution. Summing absolute scatter contributions in the
scale keeps it meaningful when different strain rows cancel in the net
force.
Pressure proposal, mass mismatch and qualification
Run existing StaticObstaclePressure::project only on
private scratch holding v_hat. Its solver settings,
iteration limit and cancellation remain explicit proposal restrictions.
Its ordinary residual, divergence and energy budgets are insufficient to
qualify the experiment’s caller state.
Let P_if be +1 at a face’s head and
-1 at its tail. Thus Q(u)=-P(A*u), and
g_f=(P^T p)_f=p_head-p_tail. The exact projection matched
to the stored mass has correction
v-dt*(A/m)*g and pressure matrix
L=P diag(A^2/m) P^T. Existing pressure code separately
rounds rho*A*d, rho*d, and
A/(rho*d). Even bit-identical pressure and strain masses do
not establish the real-number identity m/(rho*d)=A. Do not
use that identity to declare the existing rounded pressure proposal
mass-matched.
Instead, for its actual stored candidate z_hat and
proposed pressure p, enclose the defect against the
stored-mass reference:
e_pressure_f = m_f (z_hat_f-v_hat_f) + dt*A_f*g_f,
s_pressure_f = abs(m_f (z_hat_f-v_hat_f)) + abs(dt*A_f*g_f).
Require the analogous coordinate inequality with an explicit
dimensionless 0 <= tau_pressure <= 1e-8, without an
absolute floor. This includes both arithmetic rounding and the existing
metric mismatch. The mismatch is neither silently discarded nor asserted
to be zero. Require finite pressure, valid gauges, unchanged zero wall
traces, and the independent final interval divergence gate on
all wet cells.
Finally enclose the actual pressure-stage energy difference
DeltaH_pressure = sum_f (m_f/2)
(z_hat_f-v_hat_f) (z_hat_f+v_hat_f)
and require its upper endpoint to be at most zero. Both stages must pass separately. A pressure energy decrease cannot hide a failed viscous stage.
For clarity, the following exact identities explain what an
approximate pressure solve can and cannot imply. With
r=P(A*v_hat)/dt-L*p and the defect above,
Q(z_hat) = -dt*r - P(A*e_pressure/m),
H(z_hat)-H(v_hat)+H(z_hat-v_hat)
= dt*sum_i p_i Q_i(z_hat) + sum_f e_pressure_f*z_hat_f.
Consequently the solver’s small rounded residual alone proves neither actual divergence nor energy decrease. The final flux and energy enclosures are the acceptance authority. The per-face defect gate binds that accepted state to the stated numerical momentum equation.
Arithmetic premise and bounded transaction
The enclosure engine uses closed binary64 intervals and outward
rounding at every basic operation. Under
round-to-nearest, ties-to-even scalar basic operations, an endpoint
operation is expanded with next_down/next_up;
product and quotient extrema include all endpoint combinations. Division
requires a denominator interval strictly separated from zero. No fused
or reassociated expression may replace the specified operation sequence.
Exact zero and identity cases may return point intervals only when
established algebraically, such as multiplication by a point zero,
adding point zero, or subtracting equal point inputs. Merely obtaining a
rounded zero is not evidence of an exact identity.
The supported experiment environment is Linux x86_64 under Rust’s
documented scalar floating-point semantics: default round-to-nearest and
no flush-to-zero or altered floating-point controls. Refuse unsupported
targets, NaN, infinity, overflow, nonzero multiplication/division
underflow to zero, subnormal inputs, subnormal intermediate results or
outward endpoints, invalid divisions and unresolved required
inequalities. Conservative refusals at an interval boundary are allowed.
In particular, blindly widening zero produces subnormal endpoints; the
documented exact identity cases are necessary for the resting state. Rust
RFC 3514 states the basic-operation and floating-environment
assumptions; Rust’s
next_up and next_down documentation
specifies adjacent representable endpoints. The module can refuse
unsupported targets and observed arithmetic-probe failures, but it does
not introspect floating-point control registers or prove that external
code never changes them. The documented standard environment is an
explicit premise; externally altered controls are unsupported. These are
external arithmetic premises, not a Lean proof of the Rust compiler or
machine execution.
Construction checks integer products and sums, fallible allocation
and actual vector capacity payload against a caller cap. Account for the
borrowed strain’s reported payload, pressure payload, full MAC proposal
arrays and all interval scratch in the declared combined cap; state
explicitly that borrowed geometry, caller arrays, stack, allocator
metadata and process RSS are outside this cap. Preallocate scratch
before stepping. Iteration caps and cancellation bound work; the
workspace and its operator/pressure call paths allocate no heap memory
during a step, change no geometry and preserve the borrowed operator.
Caller cancellation callbacks remain caller code and are outside that
allocation claim. On any refusal, caller velocity and any caller-visible
accepted pressure, counter or report remain unchanged. Publication
occurs only after every acceptance gate and a final cancellation
checkpoint. Scratch need not roll back. The wrapper describes an
interval of length dt; it does not introduce an independent
simulation clock or silently shorten the requested interval.
Units, evidence and proof boundary
| Quantity | Units |
|---|---|
u, v_hat, z_hat |
m/s |
E, w, m |
1/m, m^3, kg |
rho, mu, dt |
kg/m^3, Pa*s, s |
K*u, -mu*K*u |
m^2/s, N |
mu*D0, H, B |
W, J, m/kg |
Q, Q/V, p,
r |
m^3/s, 1/s, Pa,
m^3/s^2 |
| momentum defects and their scales | kg*m/s |
The exact-real Euler coefficient theorem already supplies a
conditional reference result. New proof obligations are the stored-mass
pressure defect identities above and composition: sound enclosures of
both energy differences with nonpositive upper endpoints imply
H(z_hat)<=H(u). Sound enclosures of flux ratios and
momentum defects imply the stated tolerance inequalities. Enclosure
containment is an explicit premise in Lean; interval implementation,
native source correspondence and the floating-point environment require
their own reviewed tests and qualification evidence. No exact theorem or
unenclosed numeric B=17 authorizes an IEEE step by
itself.
A planned independent rational qualification fixture uses the unit
3^3 grid, center box [1,2]^3,
rho=mu=1, and dt=1/32. All face velocities are
zero except u_x(1,0,0)=1/2, u_x(1,1,0)=-1/2,
u_y(0,1,0)=-1/2, and u_y(1,1,0)=1/2, where
coordinates index the respective MAC face array. This curl has zero
initial flux in all 26 wet cells. Its exact targets are initial energy
1/2, viscous energy 679/2048, final projected
energy 303995/917504, and maximum post-viscosity integrated
flux 1/64. The nonzero intermediate flux requires a genuine
pressure correction. These targets must be reproduced from the fixture
and compared with the experiment’s outward enclosures; listing them is
not a test receipt. Rest, refusal and rollback cases are additional
obligations.
Batty and Bridson (2008), section 3 (PDF page 4), describes splitting viscosity and pressure; section 5, equations (9)–(11) (PDF page 5), derives symmetric-strain dissipation and an implicit variational update. This experiment’s bounded explicit integration and acceptance gates are new choices. Batty, Bertails and Bridson (2007), equations (4)–(6) (PDF page 4), supplies the mass-weighted kinetic projection principle. Neither paper supplies these interval gates or the stored-mass defect qualification.
An implicit follow-on would need its own solver and residual-work
qualification: for r_v=M(v-u)+dt*mu*K*v, the exact identity
is H(v)-H(u)+H(v-u)+dt*mu*D0(v)=sum_f r_v_f*v_f. A small
residual norm alone does not imply nonincrease. This first experiment
therefore remains explicit. It excludes advection, forcing, transport,
capillarity, free surfaces, variable materials, moving solids and global
PDE convergence claims.