Physics in Parallel
Physics in Parallel is a Rust crate for building physics-oriented numerical simulations from reusable layers. The design goal is to let domain users work with familiar concepts such as scalars, tensors, spaces, particles, boundaries, laws, and interactions while hiding backend memory layout and parallel traversal details.
The crate is organized from lower-level infrastructure to higher-level model code:
math -> space -> engines -> models
mathdefines scalar algebra, rank-N tensors, matrices, vector batches, random fillers, and math IO.spacedefines continuous-space utilities and discrete square-lattice spaces.enginesdefines model-agnostic runtime storage, reducers, interaction topology, and neighbor-list infrastructure.modelsdefines validated physical laws and canonical massive-particle model pieces.
Common import:
use *;
Narrower imports are also available:
use *;
use *;
use *;
use *;
Examples
The runnable examples are documented in EXAMPLES.md. That guide introduces each example, explains what it does, shows the command-line arguments, and describes how to interpret benchmark or demonstration output.
Design Rules
Core consistency rules used across the crate:
- Lower modules should be reused by higher modules. For example, particle boundaries call
space::continuousboundary logic, particle randomization callsspace::continuous::sampling, and particle interactions useengines::soa::Interaction. - Public APIs should expose physical or mathematical concepts, not backend layout. Internal storage helpers are kept behind
pub(crate)where possible. - Type-preserving math operations keep the same scalar type and backend when the operation is mathematically backend-preserving.
- Explicit conversion APIs have explicit names such as
try_cast_to,cast_to,to_dense,to_sparse, andto_ndarray. - Boolean particle masks use compact numeric storage internally, while users normally call bool-facing helpers such as
set_alive,is_alive,set_rigid, andis_rigid.
Math
Purpose:
math is the numeric foundation. It provides scalar traits, generic rank-N tensors, rank-2 matrix wrappers, vector-list batches, random fillers, and IO conversion traits.
Scalar
Purpose:
Scalar gives integers, real floats, and complex values one common number-like interface. It separates operations that preserve the scalar type from projection/construction/casting operations that intentionally cross type boundaries.
Core API:
zero
one
from_real
real
imag
conj
abs
sqrt
exp
ln
sin
cos
pow
norm_sqr
norm_sqr_real
Core types:
ScalarScalarSerdeScalarCastErrorComplex
Rank-N Tensor
Purpose:
Tensor<T, Backend> is the general tensor facade. It lets users address tensors by shape and coordinate while dense/sparse storage and parallel element traversal stay behind the API.
Core creation API:
empty
zeros
from_vec
from_fn
empty
from_triplets
Core access API:
tensor.shape
tensor.rank
tensor.size
tensor.get
tensor.get_mut
tensor.set
tensor.fill
tensor.print
Type-preserving math API:
&tensor + &rhs
&tensor - &rhs
tensor.elem_mul
tensor.elem_div
tensor.scalar_mul
tensor.conj
tensor.abs
tensor.sqrt
tensor.transpose
tensor.hermitian_transpose
Explicit conversion and linear algebra API:
tensor.
tensor.
tensor.to_dense
tensor.to_sparse
tensor.dot
tensor.hermitian_dot
tensor.matmul
tensor.cross
tensor.wedge
tensor.norm_sqr
tensor.norm_sqr_real
Core types:
Tensor<T, DenseBackend>Tensor<T, SparseBackend>TensorTraitTensorErrorTensorResult
Tensor Random Fillers
Purpose:
TensorRandFiller fills dense tensor storage in parallel. It is the shared random infrastructure used directly by tensors and indirectly by vector-list random generators and continuous-space sampling.
Core API:
new
new_with_rng_kind
filler.refresh
filler.try_refresh
filler.rng_kind
Core types:
TensorRandFillerRandTypeRngKindTensorRandError
Matrix
Purpose:
Matrix<T, Backend> is a rank-2 wrapper over rank-N tensor infrastructure. Dense and sparse matrices use rank-N tensor backends; structured matrices such as diagonal, symmetric, antisymmetric, and triangular matrices store only the independent entries and infer the rest.
Core creation API:
empty
from_vec
empty
from_triplets
empty
empty
empty
empty
empty
empty
empty
Core API:
matrix.shape
matrix.rows
matrix.cols
matrix.size
matrix.get
matrix.set
matrix.fill
matrix.print
matrix.add
matrix.sub
matrix.elem_mul
matrix.elem_div
matrix.scalar_mul
matrix.transpose
matrix.hermitian_transpose
matrix.trace
matrix.matmul
matrix.
matrix.
matrix.to_dense
matrix.to_sparse
matrix.to_dense_matrix
Core types:
DenseMatrix<T>SparseMatrix<T>DiagonalMatrix<T>SymmetricMatrix<T>AntiSymmetricMatrix<T>UpperTriangularMatrix<T>LowerTriangularMatrix<T>StrictUpperTriangularMatrix<T>StrictLowerTriangularMatrix<T>
VectorList
Purpose:
VectorList<T> stores many fixed-length vectors as dense rank-N storage with logical shape [num_vectors, dim]. It is used when the natural unit of manipulation is a vector row, not an individual scalar.
Core API:
empty
zeros
from_vec
from_fn
vectors.dim
vectors.num_vectors
vectors.shape
vectors.get
vectors.set
vectors.get_vec
vectors.get_vec_mut
vectors.get_vec_owned
vectors.set_vec
vectors.axis
vectors.fill
vectors.print
vectors.par_for_each_vec
vectors.par_for_each_vec_mut
vectors.scale_vectors_by_list
vectors.normalize
vectors.norms_real
vectors.
vectors.
Random vector batches:
new
haar.refresh
new
nn.refresh
Core types:
VectorList<T>VectorListRandHaarVectorsNNVectors
Math IO
Purpose:
math::io handles external-format interop for math containers. JSON payloads use compact shape/data schemas, while ndarray conversions preserve logical shape and row-major element order.
Core API:
to_string_pretty
value.to_ndarray
from_ndarray
value.to_tensor_string
from_tensor_string
Core types:
NdarrayConvertToJsonPayloadFromJsonPayloadFlatPayload<T>TensorStringConvert
Space
Purpose:
space adds physical coordinate semantics on top of math data structures. It contains continuous-space tools and discrete square-lattice spaces.
Continuous Boundary
Purpose:
Continuous boundaries define how real-valued coordinate vectors are returned to an axis-aligned domain. The pure boundary code is independent of particles and can operate on one vector or a flat list of vectors.
Core API:
new
new
new
boundary.dim
boundary.min
boundary.max
boundary.apply_position
boundary.apply_position_velocity
boundary.apply_positions
boundary.apply_positions_velocities
Core types:
ContinuousBoundaryPeriodicBoxClampBoxReflectBoxBoundaryError
Continuous Sampling
Purpose:
Continuous sampling fills VectorList<f64> values with common coordinate or velocity initialization patterns. Particle state construction delegates to this module for generic continuous-vector randomization.
Core API:
sample_vectors
sample_vectors
sample_vectors
sample_vectors
Core types:
VectorSamplingMethodVectorSamplingError
Space Trait
Purpose:
Space<T> gives higher-level code a common interface for spatial containers without exposing each container's storage or boundary implementation.
Core API:
space.data
space.dims
space.linear_size
space.get
space.get_mut
space.set
space.set_all
space.save
SquareLattice
Purpose:
SquareLattice<T> represents square, cubic, or hypercubic lattice sites over a tensor-style shape such as [128], [64, 64], or [32, 64, 16].
Core API:
new
periodic
reflective
cfg.shape
cfg.rank
cfg.num_sites
cfg.tensor_shape
new
vacancy
lattice.data
lattice.set_vacant
lattice.is_vacant
lattice.fill_vacancy
lattice.downsample
lattice.rescale
Core types:
SquareLattice<T>SquareLatticeConfigSquareLatticeInitMethod<T>BoundaryConditionVacancyValue
Square-Lattice Kernels And Pair Generation
Purpose:
Kernels define random displacement rules for square-lattice workflows. RandPairGenerator creates source coordinates, raw displacements, and raw targets. Boundary interpretation is intentionally left to SquareLattice access methods.
Core API:
create_kernel
kernel.sample
kernel.kind
new
gen.refresh
gen.refresh_sources
gen.refresh_displacements
gen.refresh_targets
gen.sources
gen.displacements
gen.targets
gen.source
gen.displacement
gen.target
Core types:
KernelKernelTypeNearestNeighborKernelUniformKernelPowerLawKernelRandPairGeneratorSourceMode
Space IO
Purpose:
space::io contains IO behavior for space types. Current ready support is square-lattice JSON and ndarray conversion.
Core API:
save_square_lattice
to_string_pretty
from_ndarray
lattice.to_ndarray
lattice.serialize
Engines
Purpose:
engines provides model-agnostic runtime infrastructure. The ready backend is structure-of-arrays storage, where each attribute is stored as a typed vector-list column.
Reducers
Purpose:
Reducers combine batches of observed values without knowing which model produced the values.
Core API:
MeanReducer.reduce
Core types:
Reducer<T>MeanReducer
PhysObj And Attribute Storage
Purpose:
PhysObj stores many simulation objects as named typed attribute columns. Each column is a VectorList<T> with shape [n_objects, dim]. Attribute labels are the normal user path; generated attribute IDs are available for repeated expert lookups.
Core API:
empty
new
empty
core.
core.insert
core.remove
core.rename
core.contains
core.labels
core.n_objects
core.id_of
core.label_of
core.
core.
core.
core.
core.
core.
core.
core.dim_of
core.type_name_of
empty
new
obj.serialize
obj.save_to_json
Core types:
AttrsMetaAttrsCoreAttrsErrorAttrIdPhysObj
Interaction Storage
Purpose:
InteractionTopology maps participating object IDs to stable interaction IDs. Interaction<T> combines topology with payload storage, so topology edits and payload edits stay synchronized.
Core API:
new
with_order
topology.set_order
topology.set_n_objects
topology.prune_n_objects
topology.add
topology.remove
topology.id_of
topology.nodes_of
topology.add_pair
topology.remove_pair
new
with_topology
interaction.set
interaction.get
interaction.get_mut
interaction.remove
interaction.set_pair
interaction.get_pair
interaction.remove_pair
interaction.par_for_each
interaction.par_for_each_payload_mut
Core types:
InteractionTopologyInteraction<T>InteractionNodesInteractionOrderInteractionErrorObjIdInteractionId
NeighborList
Purpose:
NeighborList is a cell-linked candidate-pair generator. It emits unique unordered candidate pairs from same/adjacent cells but does not apply a final physical cutoff distance.
Core API:
new
neighbor_list.rebuild
neighbor_list.for_each_pair_candidate
neighbor_list.collect_pair_candidates
neighbor_list.clear
neighbor_list.dim
neighbor_list.num_objects
neighbor_list.cells_per_axis
Core types:
NeighborListNeighborListError
Models
Purpose:
models contains concrete physical model pieces built on the lower layers. Current ready modules cover validated law payloads and canonical massive-particle simulation components.
Laws
Purpose:
models::laws stores small validated parameter payloads. These payloads do not know how objects are stored; model adapters decide how to apply them to particle state, lattice sites, or future model objects.
Core API:
new
spring.validate
new
power_law.validate
Core types:
SpringSpringCutoffSpringLawErrorPowerLawDecayPowerLawRangePowerLawError
Particle Attributes And State Construction
Purpose:
Particle modules use a canonical PhysObj layout. Vector attributes r, v, and a have shape [num_particles, dim]. Scalar attributes m, m_inv, alive, and rigid have shape [num_particles, 1].
Core attribute API:
set_alive
is_alive
set_rigid
is_rigid
alive_value
rigid_value
AliveOnly
All
Core construction/randomization API:
create_template
randomize_r
randomize_v
randomize_v
randomize_v
Core types:
ParticleSelectionMassiveParticlesErrorVelocitySamplingMethod
Particle Boundary
Purpose:
Particle boundary adapters apply space::continuous boundary objects to canonical particle state. The continuous boundary owns the geometric rule; the particle adapter owns traversal over ATTR_R, velocity updates in ATTR_V, and alive/rigid mask handling.
Core API:
new?.apply_to_particles
new?.apply_to_particles
new?.apply_to_particles
Core types:
ParticleBoundaryParticleBoundaryError
Particle Integrators
Purpose:
Integrators advance canonical particle r and v from a. They skip dead particles and rigid particles; they do not clear acceleration after stepping.
Core API:
ExplicitEuler.apply
SemiImplicitEuler.apply
Core types:
IntegratorExplicitEulerSemiImplicitEulerIntegratorError
Particle Thermostat
Purpose:
LangevinThermostat applies an exact Ornstein-Uhlenbeck velocity update to canonical particle velocities. It honors ParticleSelection for alive/dead behavior and always skips rigid particles.
Core API:
new
thermostat.apply
thermostat.tau_target
thermostat.gamma
thermostat.seed
thermostat.step_counter
thermostat.selection
Core types:
ThermostatLangevinThermostatThermostatError
Particle Observers
Purpose:
Particle observers compute read-only scalar summaries from canonical particle state. AliveOnly skips dead particles, while All intentionally includes every allocated slot for diagnostics.
Core API:
default.observe
new.observe
default.observe
new.observe
Core types:
ObserverKineticEnergyObserverTemperatureObserverObserveError
Particle Interactions
Purpose:
Particle interaction modules wrap engine-level interaction storage with particle-specific validation and application rules.
Core API:
from_bounds
from_box
neighbor_list.rebuild
neighbor_list.collect_pairs
empty
springs.add_spring
springs.add_spring_payload
springs.get_spring
springs.remove_spring
springs.apply_hooke_acceleration
empty
network.add_power_law
network.add_payload
network.get_power_law
network.remove_power_law
Core types:
ParticleNeighborListParticleNeighborListErrorSpringNetworkSpringNetworkErrorPowerLawNetworkPowerLawNetworkError
Examples
Runnable examples and benchmark usage are documented in EXAMPLES.md. Common entry points:
Verification
Standard checks: