Container and Facade Migration
July 25, 2026 ยท View on GitHub
This page maps legacy particle and gas facades to their data-container equivalents. See the migration overview for ownership and support boundaries.
Quick migration
Particle data (before to after)
import numpy as np
import particula as par
# Legacy facade
rep = par.particles.ParticleRepresentation(
strategy=par.particles.MassBasedMovingBin(),
activity=par.particles.ActivityIdealMass(),
surface=par.particles.SurfaceStrategyMass(),
distribution=np.array([1e-18, 2e-18, 3e-18]),
density=np.array([1200.0]),
concentration=np.array([1e5, 1e5, 1e5]),
charge=np.zeros(3),
volume=1e-6,
)
# New data container
from particula.particles import ParticleData
data = ParticleData(
# (n_boxes, n_particles, n_species)
masses=rep.get_species_mass()[None, ...],
concentration=rep.get_concentration()[None, ...],
charge=rep.get_charge()[None, ...],
density=rep.get_density(),
volume=np.array([rep.get_volume()]),
)
Gas data (before to after)
import numpy as np
import particula as par
# Legacy facade
species = par.gas.GasSpecies(
name="Water",
molar_mass=0.018,
vapor_pressure_strategy=par.gas.ConstantVaporPressureStrategy(2330.0),
concentration=1e-6,
)
# New data container
from particula.gas import GasData
gas_data = GasData(
name=["Water"],
molar_mass=np.array([0.018]),
concentration=np.array([[1e-6]]), # (n_boxes, n_species)
partitioning=np.array([True]),
)
ParticleRepresentation to ParticleData
Constructor mapping
| Legacy input | ParticleData field | Notes |
|---|---|---|
distribution | masses | Convert to per-species masses. |
density | density | 1D array of species densities. |
concentration | concentration | Shape (n_boxes, n_particles). |
charge | charge | Shape (n_boxes, n_particles). |
volume | volume | Shape (n_boxes,). |
strategy | behavior | Keep strategy separate from data. |
activity | behavior | Remains in activity strategies. |
surface | behavior | Remains in surface strategies. |
Property and method mapping
| Legacy API | ParticleData equivalent | Notes |
|---|---|---|
get_radius() | data.radii | Computed from mass and density. |
get_mass() | data.total_mass | Total per particle. |
get_species_mass() | data.masses | Per-species masses. |
get_density() | data.density | Density per species. |
get_concentration() | data.concentration | 2D array by box. |
get_charge() | data.charge | 2D array by box. |
get_volume() | data.volume | Per-box volume. |
get_effective_density() | data.effective_density | Mass-weighted density. |
get_total_concentration() | data.concentration.sum(axis=1) | Per box. |
!!! note
ParticleData keeps the batch dimension. If you used a single-box facade,
index data.concentration[0] or data.radii[0] for the legacy shape.
GasSpecies to GasData
Constructor mapping
| Legacy input | GasData field | Notes |
|---|---|---|
name | name | List of species names. |
molar_mass | molar_mass | 1D array of molar masses. |
concentration | concentration | Shape (n_boxes, n_species). |
partitioning | partitioning | 1D boolean array. |
vapor_pressure_strategy | behavior | Remains on the facade. |
Property and method mapping
| Legacy API | GasData equivalent | Notes |
|---|---|---|
get_name() | data.name | List of names. |
get_molar_mass() | data.molar_mass | 1D array. |
get_concentration() | data.concentration[box_index] | Select a box. |
get_partitioning() | data.partitioning | Boolean mask by species. |
!!! note
Vapor pressure calculations remain on GasSpecies. Use the facade when
strategy-driven behavior is required, and pass GasData where only data
is required.
GasData and WarpGasData migration summary
For the canonical transfer boundary and support limits, see Data Containers and GPU Foundations.
Migration-focused rules of thumb:
- Keep the leading box axis explicit. Single-box gas arrays still use
(1, n_species). - Treat
nameas caller-owned metadata at the restore boundary. Supplying the original ordered names gives a semantic round trip; omittingnameor passingname=Noneproduces placeholders only. - Treat
partitioningas a CPU boolean API and a GPU numeric mask. - Treat
vapor_pressureas GPU sidecar process state that must be preserved or recomputed outsideGasDataafter restore.
Example CPU-to-GPU-to-CPU handoff:
import numpy as np
from particula.gpu import from_warp_gas_data, to_warp_gas_data
vapor_pressure = np.array([[2330.0, 120.0]]) # (1, n_species)
gpu_gas = to_warp_gas_data(
gas_data,
device="cpu",
vapor_pressure=vapor_pressure,
)
restored = from_warp_gas_data(gpu_gas, name=gas_data.name)
# Preserve ordered names outside WarpGasData and keep any vapor-pressure
# sidecar separately (or recompute it) on the CPU side.
Gradual migration with .data
Both legacy facades expose their underlying data containers:
particle_data = rep.data
gas_data = species.data
To wrap data without emitting deprecation logs, use each facade's class method:
rep = par.particles.ParticleRepresentation.from_data(
data=particle_data,
strategy=par.particles.MassBasedMovingBin(),
activity=par.particles.ActivityIdealMass(),
surface=par.particles.SurfaceStrategyMass(),
distribution=particle_data.total_mass[0],
)
species = par.gas.GasSpecies.from_data(
data=gas_data,
vapor_pressure_strategy=par.gas.ConstantVaporPressureStrategy(2330.0),
)
Conversion helpers
Use conversion helpers when bridging old and new APIs:
from_representationandto_representationfor particle data. They are exported fromparticula.particles.from_speciesandto_speciesfor gas data. They are exported fromparticula.gas.
from particula.gas import from_species
from particula.particles import from_representation
particle_data = from_representation(rep, n_boxes=1)
gas_data = from_species(species, n_boxes=1)