Physics in Parallel
Alpha and breaking API notice: PiP is under active design. Version 3.6.0 is the current API contract; every version before 3.6.0 is considered broken and unsupported. Versions still increase normally, but any alpha release may contain breaking changes. Pin the exact version used by a scientific project.
Physics in Parallel (PiP) provides reusable, multicore numerical building blocks for simulations: tensors, matrices, vector batches, spatial sampling, lattices, pair generation, and ready-to-use particle models.
API contract
PiP deliberately has three non-overlapping preludes:
use *; // foundational user API
use *; // ready physical models
use *; // backend and extension API
Import only the layers a program uses. No prelude imports another. The old crate-wide and domain-specific preludes no longer exist.
The basic and models symbols listed below are the complete normal user API.
The opt-in backend API is catalogued in advanced_api.md.
Anything not re-exported by one of these preludes is implementation detail and
cannot be imported by downstream crates.
Some foundational container types have inherent methods whose signatures use advanced-only backend types. Those methods are advanced API despite living on the same Rust type; the signature makes the boundary explicit.
PiP itself follows the same dependency rule: compose the basic API first, use the advanced API only when it supplies a necessary capability, and access an internal implementation only when a public route would materially harm performance or cannot express the operation.
Basic API
physics_in_parallel::prelude::basic exports exactly these symbols:
- Randomness:
RngConfig,RngMethod,RngConfigError,IndexedRng. - Internal execution policy:
set_parallel_partitions,parallel_partitions,DEFAULT_PARALLEL_PARTITIONS,ParallelismError. - Scalars:
Scalar,Complex,ScalarCastError. - Dense mathematics:
Tensor,TensorError,Matrix,DenseMatrix,MatrixError,VectorList. - Random filling:
RandType,TensorRandFiller,TensorRandError. - Continuous space:
BoundaryError,ContinuousBoundary,ClampBox,PeriodicBox,ReflectBox,VectorSamplingMethod,VectorSamplingError,sample_vectors. - Square lattices:
BoundaryCondition,SquareLatticeConfig,SquareLatticeConfigError,SquareLattice,SquareLatticeInitMethod. - Pair generation:
PairGeneratorConfig,PairGenerator,PairingMethod,SourceMode,KernelType,KernelError,PairGenerationError.
The core container conventions are consistent:
Tensoruses a row-major shape and signed coordinates. Coordinate and flat accessors both wrap periodically, including negative and oversized indices.Matrixuses signed(row, column)and flat access with periodic wrapping. Arithmetic keeps the backend when that is mathematically valid. Scalar multiplication is namedscalar_mul;mul_vectors_intoapplies one matrix to a caller-owned contiguous vector batch.VectorListstoresnum_vectorsrows of dimensiondim; usevector,vector_mut,vector_owned,set_vector,axis, andset_axisfor row/axis access.SquareLatticeexposes coordinate and flat forms ofget,get_mut, andset, plusshape,rank,num_sites, andfill, without requiring the advancedSpacetrait. Every accessor applies its configured boundary.SquareLatticeInitMethod::ShuffledValuesaccepts one complete flat row-major value list and applies a reproducible unbiased permutation before constructing the shaped lattice. The shuffle machinery remains internal to PiP.
Dense Tensor, Matrix, and VectorList provide constructors, shape/access
methods, elementwise arithmetic, scalar_mul, casts, and Serde. Tensor
additionally provides mapping and tensor algebra such as transpose, dot, norm,
cross, wedge, and matrix multiplication. Matrix additionally provides
transpose, Hermitian transpose, trace, matrix multiplication, and abs.
VectorList additionally provides parallel row traversal, per-row scaling,
norms, normalization, and polar decomposition. Rustdoc is the exact signature
reference.
Randomness
RngConfig is the only randomness configuration accepted by normal stochastic
APIs. A missing seed uses host entropy; a missing method uses the component's
documented default. Long-lived generators expose their resolved configuration.
Indexed filling and pair generation are deterministic independently of Rayon
scheduling and PiP's execution partition setting.
Internal parallelism
PiP uses the current Rayon pool; it never creates or owns another thread pool. Its low-level operations create at most eight partitions by default so a task can coexist with higher-level parallel tasks. A program may set a different process-wide limit once, before the first PiP parallel operation:
use *;
set_parallel_partitions.expect;
The limit controls PiP work partitioning, not Rayon worker count. Higher-level
workflow concurrency remains the responsibility of the caller. The value is
frozen after first use; later attempts return ParallelismError.
Pair generation
Construct a PairGeneratorConfig, then a PairGenerator from the lattice
shape. Every pairing method produces the same meanings and shapes: one source
site and one target site per pair. PairingMethod::IndependentUniform samples
source and target independently over the full shape and allows self-pairs.
Kernel-based methods instead sample a displacement. Their raw target
coordinates can lie outside the declared shape and must be passed to
SquareLattice access methods, whose indexing rules resolve the boundary.
Users do not add boundary logic to the generator.
Models API
physics_in_parallel::prelude::models exports exactly these symbols:
- State:
PhysObj,AttrsError,create_template,MassiveParticlesError,VelocitySamplingMethod,randomize_r,randomize_v. - Canonical attributes:
ATTR_R,ATTR_V,ATTR_A,ATTR_M,ATTR_M_INV,ATTR_ALIVE,ATTR_RIGID,ParticleSelection,set_alive,is_alive,set_rigid,is_rigid. - Boundaries:
ParticleBoundary,ParticleBoundaryError. - Integration:
Integrator,IntegratorError,ExplicitEuler,SemiImplicitEuler. - Thermostats:
Thermostat,ThermostatError,LangevinThermostat. - Observation:
Observer,ObserveError,KineticEnergyObserver,TemperatureObserver. - Laws:
Spring,SpringCutoff,SpringLawError,PowerLawDecay,PowerLawRange,PowerLawError. - Interactions:
SpringNetwork,SpringNetworkError,PowerLawNetwork,PowerLawNetworkError,ParticleNeighborList,ParticleNeighborListError.
PhysObj is the canonical system state, so users do not need a wrapper struct.
Its normal API exposes metadata, object count, typed attribute access, typed
attribute-vector access, mutation, serialization, and JSON persistence.
Boolean state is accessed through the bool-facing helpers; its compact numeric
encoding is internal.
Serialization
Scientific containers implement Serde directly. Dense data is row-major; sparse data uses canonical sorted flat indices; heterogeneous particle attributes preserve stable IDs and scalar types. Invalid shapes, scalar mismatches, malformed sparse entries, unsupported schema versions, and non-finite JSON numbers are rejected during reconstruction.
PiP owns numerical data formats, not workflow policy. Checkpoint cadence, directories, queues, run metadata, and resumption belong to the consuming workflow crate.
Examples
See EXAMPLES.md. Run an example with:
Development contract
- Higher layers reuse lower-layer APIs instead of duplicating algorithms.
- Inferable information is not requested again at downstream call sites.
- Backend and layout details stay out of normal user code.
- New public functionality is composed from existing APIs whenever possible.
- Advanced additions require a concrete use case not covered by the basic or models API.