Condensation Stiffness Study and Recommendation Record¶
This note is the canonical decision record for GPU condensation integration.
The shipped production path uses four fixed equal substeps; P2/P3 candidate
comparisons remain historical evidence only. The current production GPU path is
float64 bounded and couples P2-finalized particle transfer to gas
concentration; this remains a narrow direct-kernel contract rather than a
general GPU production claim.
Current Runtime Scope¶
- Production path: explicit fixed-four GPU condensation. Every successful
condensation_step_gpu(...)call performs exactly fourtime_step / 4.0substeps. - Particle and gas update: each raw proposal is P2-finalized against inventory, then applied to particle mass and coupled to gas concentration by the matching particle-concentration-weighted transfer.
- Per-substep order: optionally refresh composition-weighted surface tension,
overwrite
gas.vapor_pressure, refresh environment properties, produce a raw transfer proposal, P2-finalize and apply it, accumulate the finalized transfer, and couple gas concentration. Later proposals read coupled gas; vapor-pressure refresh does not read gas concentration. - Transfer buffers: the resolved total transfer is cleared once after preflight and accumulates P2-finalized transfer over all four substeps. A supplied total buffer is returned by identity; the separate work buffer retains only the final raw proposal.
- Failure boundary: invalid aggregate P2 state or sidecars fail before launches or mutation. A later non-finite fresh proposal fails before P2 mutation in that cycle but does not roll back earlier completed substeps.
- Baseline backend for this phase:
np.float64inputs and Warp CPU execution. - Accepted study inputs: scalar
temperatureandpressure, direct Warp arrays with shape(n_boxes,), and the tested hybrid mode where one direct input stays scalar while the other uses a Warp(n_boxes,)array. - Study cases are deterministic fixed-shape builders that should be recreated from clean inputs after failed validation or intentionally unstable runs.
- Recommendation dependency boundary: the conclusions below assume the shipped
E2-F2 environment-shape contract for scalar or direct Warp
(n_boxes,)temperature and pressure inputs, and they stay inside the E2-F6float64evidence envelope.
Shared Case Catalog¶
The executable test baseline defines three named regimes:
nanometeraccumulation_modedroplet_like
Each CondensationStiffnessCase declares:
namen_boxesn_particlesn_speciestime_step- scalar baseline
temperatureandpressure - deterministic scaling for particle mass, gas concentration, and vapor pressure
- optional zero-mass or zero-concentration particle edges
The important contract is fixed shape, not random sampling. Every case rebuilds
deterministic particle, gas, vapor-pressure, and environment inputs with
explicit (n_boxes, n_particles, n_species) and (n_boxes,) dimensions.
Shared Metrics and Classification¶
The baseline tests use the following helper concepts:
_particle_mass_is_nonnegative: all post-step particle masses are>= 0._particle_values_are_finite: particle/gas/support arrays remain finite._fractional_mass_change_per_bin: fractional change is computed only for positive initial masses, so zero-initial-mass bins need a separate stability check._zero_mass_entries_remain_stable: zero-initial-mass bins remain at zero so the zero-mass edge stays deterministic; helper inputs must have matching shapes._validate_stiffness_case_metadata: declared case metadata must match array shape andnp.float64dtype expectations._classify_particle_only_condensation_stiffness: historical test helper name retained for the recorded study; it is not the current gas-coupled runtime contract.
Boundary Semantics¶
- Fractional-mass-change thresholds are inclusive: exact equality remains
stable. - Zero-initial-mass growth remains
unstableeven though fractional change is reported only for positive initial masses. - Declared shape mismatches fail validation.
- Declared dtype mismatches fail validation.
- Zero-mass entries are treated as stable only when they remain unchanged.
- Accepted explicit
environment=...inputs with(n_boxes,)Warp arrays match accepted direct(n_boxes,)Warp-array inputs and should not mutate caller-owned temperature or pressure arrays.
Measured Recorded Timestep Grid¶
The current recorded sweep is implemented in
particula/gpu/kernels/tests/_condensation_test_support.py and exposed through
the discoverable wrapper
particula/gpu/kernels/tests/condensation_stiffness_test.py. For each named
case, the collected tests:
- execute the fixed timestep grid from
_RECORDED_TIMESTEP_GRID_BY_CASE - reuse one caller-owned preallocated
mass_transferbuffer per case/device - rebuild particle, gas, and vapor-pressure inputs before every trial
- historical baseline: record the then-current particle-only behavior; these rows do not describe the later P2-finalized gas-coupled runtime
- keep scalar
temperature/pressureinputs for single-box cases and direct Warp(n_boxes,)arrays for the multi-boxdroplet_likecase
| Case | Environment input mode | Timestep | Threshold | Classification | Notes |
|---|---|---|---|---|---|
nanometer |
scalar temperature / pressure |
0.00005 |
1.0 |
stable |
Historical particle-only baseline; caller-owned buffer reused and overwritten. |
nanometer |
scalar temperature / pressure |
0.05 |
1.0 |
stable |
Historical particle-only baseline. |
nanometer |
scalar temperature / pressure |
50.0 |
1.0 |
stable |
Historical particle-only baseline. |
accumulation_mode |
scalar temperature / pressure |
0.004 |
1.0 |
stable |
Historical particle-only baseline; caller-owned buffer reused and overwritten. |
accumulation_mode |
scalar temperature / pressure |
0.4 |
1.0 |
stable |
Historical particle-only baseline. |
accumulation_mode |
scalar temperature / pressure |
40.0 |
1.0 |
stable |
Historical particle-only baseline. |
droplet_like |
direct Warp (n_boxes,) arrays |
0.04 |
1.0 |
stable |
Historical particle-only baseline; multi-box direct arrays supported. |
droplet_like |
direct Warp (n_boxes,) arrays |
4.0 |
1.0 |
stable |
Historical particle-only baseline. |
droplet_like |
direct Warp (n_boxes,) arrays |
400.0 |
1.0 |
stable |
Historical particle-only baseline. |
Across the current recorded grid, the executable tests observe the same
historical particle-only maximum fractional-mass-change magnitude (1.0) for every row.
The baseline therefore applies one inclusive threshold (1.0) across the full
grid and records every row as stable under that shared rule. Separate unit
tests still cover the unstable branch for larger fractional changes,
zero-mass growth, and non-finite values. This is recorded-grid evidence for the
historical fixed-shape particle-only path, not evidence for the current
gas-coupled conservation contract or a general stable-timestep limit.
Candidate Evaluation Evidence¶
P2/P3 recorded two deterministic prototype candidates implemented in
particula/gpu/kernels/tests/_condensation_test_support.py and collected
through particula/gpu/kernels/tests/condensation_stiffness_test.py. They
remain test-local evidence only; the public condensation_step_gpu(...)
runtime and package export surface are unchanged. The later production path
does ship gas coupling, but these candidates remain historical evidence only.
| Candidate | Family | Buffer reuse | Determinism | Finite/non-negative masses | CPU-reference agreement | Graph capture | Autodiff note |
|---|---|---|---|---|---|---|---|
fixed_count_substeps_4 |
Historical P2/P3 fixed-count explicit sub-stepping evidence; its fixed-four behavior is now shipped. | Pass: one caller-owned mass_transfer array plus fixed-shape work/accumulator scratch reused across runs. |
Pass: repeated runs for named stiffness cases produce identical arrays. | Pass: candidate tests require finite outputs and >= 0 particle masses. |
Pass within documented rtol <= 5e-2 at the baseline timestep and max relative error <= 5e-2 across the recorded grids for nanometer, accumulation_mode, and droplet_like. These bounds are case-specific evidence, not a general accuracy tolerance or stable-timestep limit. |
Not evaluated as production graph-capture evidence. | Not evaluated as production autodiff evidence. |
asymptotic_relaxation |
Asymptotic first-order bounded relaxation | Pass: one caller-owned mass_transfer array plus one fixed-shape work scratch reused across runs. |
Pass: repeated runs for named stiffness cases produce identical arrays. | Pass: candidate tests require finite outputs and >= 0 particle masses. |
Pass within documented rtol <= 3.5e-1 at the baseline timestep and max relative error <= 3.5e-1 across the recorded grid. This looser bound is recorded as prototype evidence only and is not suitable for a production recommendation by itself. |
Pass: fixed-shape algebra with no adaptive search or variable-length loops. | exp(...) relaxation remains differentiable away from the same clamp boundary, so it is a plausible autodiff target but not yet production-qualified. |
Historical Phase Boundary Decision¶
- This decision preceded the shipped P2-finalized gas-coupled production path. The candidate coverage remains deterministic evaluation evidence, not a current runtime description.
- The asymptotic candidate remains evidence-only because the tolerance required to track the current CPU/explicit reference is materially looser than the fixed-count candidate.
- Because the candidate evidence was credible in test-local helpers, no private
production helper was added to
particula/gpu/kernels/condensation.py.
Final Recommendation¶
Shipped fixed-four implementation¶
fixed_count_substeps_4 is the shipped production integration behavior of
condensation_step_gpu(...), not a future prototype. Each valid call uses four
equal substeps, updates particle mass and gas concentration using the same
P2-finalized transfer, and keeps production calculations device resident.
Why this is the recommended path:
- The historical P2/P3 comparison recorded
rtol <= 5e-2at the baseline timestep and maximum relative error<= 5e-2only for the namednanometer,accumulation_mode, anddroplet_likegrids. - Successful calls preserve supplied total-buffer identity, clear that total once after preflight, and accumulate P2-finalized transfer. A separate work buffer retains the final raw proposal.
CondensationScratchBuffersremains a concrete-module-only sidecar. Its supplied active-device, stable-shapewp.float64fields may be omitted independently, in which case the step allocates fallback buffers.- This shipped behavior does not establish graph capture/replay or autodiff readiness.
P1--P4 production-hook evidence boundary¶
The historical candidate comparisons above used case-specific 5e-2 agreement
thresholds. They are distinct from current production-hook evidence:
| Evidence | Wrapper | Scope |
|---|---|---|
| P1 | particula/gpu/kernels/tests/condensation_test.py |
Independent NumPy-oracle parity for final particle mass and gas concentration, including one/multi-box and multi-species fixtures. |
| P2 | particula/gpu/kernels/tests/condensation_test.py |
Separate strict concentration-weighted particle-plus-gas conservation at rtol=1e-12, plus mutation and output-buffer contracts. |
| P3 | particula/gpu/kernels/tests/condensation_graph_capture_test.py |
CPU capture is capability-skipped; on CUDA, only the public-step host-validation readback during capture is strict-xfailed. Setup and normal calls remain ordinary assertions. This is a limitation, not support. |
| P4 | particula/gpu/kernels/tests/condensation_autodiff_test.py |
Raw-rate-only, one-box fp64 interior Tape derivative evidence; P2 clamps and inventory limits remain outside the derivative claim. |
Warp CPU is the standard backend for supported P1/P2 and P4 probes when Warp is
installed. CUDA is optional local/manual evidence. Fixed-four looping and stable
caller-owned buffers enable deterministic evaluation, but neither supplies a
graph-replay or general autodiff guarantee. The scope remains fp64,
fixed-four-substep, no-temperature-feedback, no-adaptive-step direct-kernel
behavior: it is not strategy/Runnable support or general CPU parity.
Focused commands are:
pytest particula/gpu/kernels/tests/condensation_test.py -q -Werror
pytest particula/gpu/kernels/tests/condensation_stiffness_test.py -q -Werror
pytest particula/gpu/kernels/tests/condensation_graph_capture_test.py -q -Werror
pytest particula/gpu/kernels/tests/condensation_autodiff_test.py -q -Werror
# Optional CUDA selections.
pytest particula/gpu/kernels/tests/condensation_test.py -q -m "warp and cuda" -Werror
pytest particula/gpu/kernels/tests/condensation_graph_capture_test.py -q -m "warp and cuda" -Werror
pytest particula/gpu/kernels/tests/condensation_autodiff_test.py -q -m "warp and cuda" -Werror
Alternatives considered but not selected¶
- Historical single-step explicit update: retained only as a P2/P3 comparison baseline; it is not the shipped production path.
asymptotic_relaxation: retain as evidence-only. It remains interesting for differentiability because the algebra is smooth away from clamp boundaries, but the measured CPU-reference agreement is materially looser (rtol <= 3.5e-1/max relative error <= 3.5e-1) than the fixed-count candidate.- Adaptive or dynamic-loop schemes: deferred; no adaptive-stepping support is documented by this record.
Current gas-coupling boundary¶
The shipped direct kernel couples each finalized transfer to gas concentration;
later mass-transfer proposals observe that updated gas state. This is not
temperature feedback, a strategy or Runnable path, adaptive stepping, graph
capture/replay, autodiff support, or general CPU-strategy parity. A failed
aggregate P2 preflight is atomic, while a later raw-proposal failure retains
completed earlier substeps rather than rolling back the whole call.
Downstream gates and dependency boundaries¶
E4-F4 P2 ships a low-level, per-substep latent-heat rate correction with
CPU-oracle/Warp parity. Issue #1272 also ships its caller-owned, signed
energy_transfer diagnostic: after successful preflight, its active-device
wp.float64 (n_boxes, n_species) output is overwritten with P2-finalized
transfer times latent heat. It does not add temperature-state
feedback, E4-F6
independent-device plus graph/autodiff evidence, or E4-F7 strategy/runnable
and final support work.
- E2-F2 environment-shape dependency: the recommendation assumes the shipped
contract for scalar inputs and explicit direct Warp
(n_boxes,)environment arrays. Broader conclusions should not be inferred for different environment ownership or shape models. - E2-F6 precision dependency: the recommendation is supported only inside
the current
float64/wp.float64evidence envelope. It does not approve a lower-precision or mixed-precision production migration.
What This Record Does Not Publish¶
This record does not publish:
- adaptive or exhaustive timestep search results
- generalized stable timestep limits
- general CPU-strategy parity or accuracy claims beyond the documented direct kernel cases
- temperature-feedback, general graph-capture/replay, or general autodiff
claims. P3 records an unsupported public-step capture constraint, and P4 is
raw-rate-only interior evidence. Issue #1272's caller-owned signed
energy_transferdiagnostic is shipped bookkeeping, not temperature feedback. - strategy/runnable-level latent-heat support
Later phases can build on this measured baseline and recommendation without redefining case shapes, metric names, or threshold meaning.