physics_in_parallel 3.6.0

High-performance infrastructure for numerical simulations in physics
Documentation
physics_in_parallel-3.6.0 has been yanked.

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 physics_in_parallel::prelude::basic::*;    // foundational user API
use physics_in_parallel::prelude::models::*;   // ready physical models
use physics_in_parallel::prelude::advanced::*; // 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:

  • Tensor uses a row-major shape and signed coordinates. Coordinate and flat accessors both wrap periodically, including negative and oversized indices.
  • Matrix uses signed (row, column) and flat access with periodic wrapping. Arithmetic keeps the backend when that is mathematically valid. Scalar multiplication is named scalar_mul; mul_vectors_into applies one matrix to a caller-owned contiguous vector batch.
  • VectorList stores num_vectors rows of dimension dim; use vector, vector_mut, vector_owned, set_vector, axis, and set_axis for row/axis access.
  • SquareLattice exposes coordinate and flat forms of get, get_mut, and set, plus shape, rank, num_sites, and fill, without requiring the advanced Space trait. Every accessor applies its configured boundary. SquareLatticeInitMethod::ShuffledValues accepts 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 physics_in_parallel::prelude::basic::*;

set_parallel_partitions(4).expect("configure PiP before its first parallel operation");

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:

cargo run --release --example <example_name> -- <arguments>

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.