Skip to content

Dilution Strategy System

The CPU dilution system provides a bounded chamber-loss process for a single Aerosol. It is the completed CPU contract from parent E6. E6-F2 is a downstream consumer of this CPU reference only; this guide does not deliver E6-F2 or CPU/GPU parity.

Public API and equation

Construct the public strategy and runnable through particula.dynamics:

import particula as par

strategy = par.dynamics.DilutionStrategy(coefficient=0.1)
dilution = par.dynamics.Dilution(strategy)
result = dilution.execute(aerosol, time_step=10.0, sub_steps=2)
assert result is aerosol

Execution mutates the supplied Aerosol and returns that same Aerosol object. For chamber volume V [m³] and dilution flow Q [m³/s], the scalar coefficient is alpha = Q / V [s⁻¹]. Every supported concentration follows the exact exponential update

c_new = c * exp(-alpha * time_step).

Here time_step is in [s], particle number concentration is in [1/m³], and gas mass concentration is in [kg/m³]. The runnable operates on CPU scalar state: elementwise particle concentration, scalar partitioning gas concentration, and multi-species gas-only concentration are supported. This does not imply multi-box transport support.

Execution, validation, and recovery

sub_steps must be a positive, non-boolean Python or NumPy integer. For the concrete exact-exponential strategy, the runnable performs one total-duration operation, independent of sub_steps, so the whole call is retry-safe. Custom compatible strategies retain equal time_step / sub_steps slice delegation. The coefficient and duration must be finite, nonnegative real scalars; complex values are rejected, and booleans and non-scalars are rejected.

A zero coefficient or zero duration is an exact no-op, but supported state is still preflighted even for a no-op. Concrete CPU dilution supports exactly one particle box and validates state before mutation. If validation fails, state is unchanged; if an unexpected setter failure occurs, already-written concentration state is rolled back. These atomicity and retry-safe failure guarantees let callers correct input and retry safely. Extreme finite decay may underflow to zero, but outputs remain finite and nonnegative.

Dilution changes only particle number concentration and gas mass concentrations. It protects particle distribution/mass, charge, density, representation volume, gas names, molar masses, partitioning metadata, and atmospheric temperature and pressure.

Boundaries and example

This CPU scalar contract excludes inlet composition or source terms, multi-box particle data and transport, GPU, Warp, CUDA, alternate-backend implementation or parity, backend selection, and performance claims.

dilute_aerosol and get_dilution_step are concrete-module-only helpers; they are not public particula.dynamics imports. Use the public strategy and runnable above for supported execution.

The deterministic, hardware-free example uses only this public API:

Focused regression commands are:

pytest particula/tests/dilution_docs_test.py -q -Werror
pytest particula/dynamics/tests/dilution_test.py -q -Werror
pytest particula/dynamics/tests/dilution_runnable_test.py -q -Werror
pytest particula/dynamics/tests/dilution_exports_test.py -q -Werror