physics_in_parallel 2.0.8

High-performance infrastructure for numerical simulations in physics
Documentation
# Physics-in-Parallel

Physics-in-Parallel is a Rust package for high-performance numerical simulation with an explicit layered architecture:

`math -> space -> engines -> models`

The main design goal is to keep low-level numeric infrastructure generic and reusable, then build domain-specific simulation tools on top of it.

---

## Architecture at a glance

### Layer order
1. `math`: scalar + tensor foundations.
2. `space`: domain and kernel abstractions built on `math`.
3. `engines`: generic simulation runtime primitives (currently SoA-focused) built on `math` and usable with `space`.
4. `models`: ready-to-use physical model packages built on `engines`.

### Top-level user-facing modules

These are exposed from `src/lib.rs`:

- `physics_in_parallel::math`
- `physics_in_parallel::space`
- `physics_in_parallel::engines`
- `physics_in_parallel::models`
- `physics_in_parallel::prelude`

`prelude` currently re-exports the crate-level math/space/engines preludes.

---

## Module details

## 1) `math`

### Purpose
`math` is the numeric foundation layer. It provides the scalar and tensor machinery used by all higher layers.

### How it is implemented

- Scalar abstraction:
  - A unified `Scalar` trait supports integers, real floats, and complex numbers behind one API.
  - Common scalar operations (conversion, norms, conjugation-style behavior, finiteness checks) are centralized here.

- Tensor core:
  - Dense backend: contiguous flat storage for cache-friendly bulk operations.
  - Sparse backend: sparse representation optimized for low occupancy patterns.
  - Unified front type: `Tensor<T, Backend>` with backend-specialized behavior under one interface.
  - Core operations are parallelized where appropriate using Rayon.

- Rank-2 math:
  - `Tensor2D` for 2D tensor views/operations.
  - `Matrix` for matrix-centric workflows and matrix traits.
  - `VectorList` for "many vectors with fixed dimension" storage and operations (logical shape `[n, dim]`).

- Random fillers:
  - `TensorRandFiller` and `RandType` support random initialization patterns reused by model code.
  - Vector-list random generators (`HaarVectors`, `NNVectors`) build on the same tensor infrastructure.

### User entry points

- `physics_in_parallel::math::*` for module-level APIs.
- `physics_in_parallel::math::prelude::*` for common math imports.

---

## 2) `space`

### Purpose
`space` adds geometric and domain semantics on top of `math` tensors. It represents simulation domains and spatial kernels without tying to a particular physical model.

### How it is implemented

- `Space` trait:
  - Shared abstraction for space/domain backends.

- Kernel module:
  - Common kernel types (`NearestNeighbor`, `PowerLaw`, `Uniform`) via `KernelType`.
  - Concrete kernel implementations and kernel factory function (`create_kernel`).

- Discrete representations:
  - Grid configuration (`GridConfig`) and initialization (`GridInitMethod`).
  - `Grid<T>` storage representation for lattice-like spaces.
  - Serialization helpers (`save_grid`) and vacancy conventions.
  - Grid JSON payloads use flat NumPy-style shape axes, plus kind tags for boundary mode (`grid_periodic` / `grid_clamped`).
  - Random pair generation utilities (`RandPairGenerator`) for stochastic displacement/workflows.

### How it builds on `math`

All concrete space data structures are implemented using math-layer tensor/scalar facilities. `space` does not duplicate numeric kernels; it composes them.

### User entry points

- `physics_in_parallel::space::*` for module-level APIs.
- `physics_in_parallel::space::prelude::*` for common space imports.

---

## 3) `engines`

### Purpose
`engines` provides model-agnostic runtime infrastructure for simulation state and interaction management.

Current primary implementation is `engines::soa`.

### How it is implemented

- `PhysObj` data container:
  - Built from `AttrsMeta` + `AttrsCore`.
  - `AttrsCore` stores heterogeneous typed columns keyed by attribute label.
  - Each attribute column is a typed `VectorList<T>` stored behind runtime-erased trait objects (`DynVectorList`), allowing mixed scalar types.
  - Enforces shape consistency (`n_objects`, per-attribute dimension checks) through `AttrsError`.

- Interaction backend:
  - `Topology`: maps mixed-arity interaction keys (e.g., `(i,j)` or `(i,j,k,...)`) to stable slot IDs.
  - Supports directed or undirected validation policy.
  - Uses hole reuse for cheap insert/delete churn.
  - `Interaction<T>` combines topology with hidden payload storage for uniform payload type `T`.
  - Exposes key-based insert/get/remove APIs and parallel payload iteration.

### How it builds on previous layers

- Builds directly on `math` data structures (`VectorList`) for SoA storage.
- Designed to work with `space` outputs (neighbor structures, kernels) but remains generic and model-independent.

### User entry points

- `physics_in_parallel::engines::soa::*`
- `physics_in_parallel::engines::prelude::*`

---

## 4) `models`

### Purpose
`models` is the domain package layer: concrete simulation model modules built from the reusable engine + math stack.

Current package: `models::particles`.

### How `models::particles` is implemented

- `attrs`:
  - Canonical attribute labels (`r`, `v`, `a`, `m`, `m_inv`, `alive`) for consistent model code.

- `create_state`:
  - `create_template(dim, num_particles)` builds a particle `PhysObj` with canonical fields.
  - `randomize_r(...)` and `randomize_v(...)` provide state initialization methods.
  - Uses math random fillers + Rayon parallel transforms for bulk initialization.

- `integrator`:
  - Integrator trait and Euler-family implementations for time stepping.
  - Operates directly on `PhysObj` attributes.
  - Uses parallel chunk-wise updates over vector-list storage.

- `boundary`:
  - Boundary trait and concrete boundary conditions (periodic, clamp, reflect).
  - Works directly on `PhysObj` canonical fields (`r`, `v`, optional `alive`).
  - Reflect boundary uses a dual-pass strategy to preserve mutable alias safety while remaining parallel.

- `thermostat`:
  - Thermostat trait and Langevin implementation.
  - Updates velocity fields from target temperature/friction parameters.
  - Validates state shape/physics constraints and applies stochastic updates.

### How it builds on previous layers

- `models` is where engine-generic containers (`PhysObj`, `Interaction`) become concrete physics workflows.
- Random initialization, vector math, and parallelism are inherited from `math`.
- State and interaction organization is inherited from `engines`.
- Optional domain logic can be composed with `space`.

### User entry points

- `physics_in_parallel::models::particles::...`
  - `attrs`
  - `create_state`
  - `integrator`
  - `boundary`
  - `thermostat`

---

## Typical usage flow

1. Use `math` to define numeric types, tensor operations, and random generators.
2. Use `space` to describe domain/kernels when your model needs geometric structure.
3. Use `engines` to hold simulation state (`PhysObj`) and interaction topology/payloads (`Interaction<T>`).
4. Use `models` packages to run concrete workflows (create state, integrate, apply boundaries/thermostats, observe).

This layering keeps the low-level infrastructure reusable while letting models stay concise and domain-focused.

---

## Serialization schema (current)

PiP uses one flat JSON payload shape for dense-like numeric data:

```json
{
  "kind": "...",
  "shape": [...],
  "data": [...]
}
```

- `shape` follows NumPy/ndarray axis convention.
- `data` is flat row-major (C-order).
- Sparse tensors currently serialize as dense payloads with `kind = "tensor_sparse"`.

Common kinds:

- `tensor`
- `tensor_sparse`
- `tensor_2d`
- `matrix`
- `vector_list` (shape is `[n, dim]`)
- `grid_periodic` / `grid_clamped`

Example payloads:

```json
{ "kind": "tensor", "shape": [2, 2], "data": [1.0, 2.0, 3.0, 4.0] }
```

```json
{ "kind": "vector_list", "shape": [2, 3], "data": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }
```

```json
{ "kind": "grid_periodic", "shape": [4, 4], "data": [0, 1, 2, 3, 4, 5, 6, 7, ...] }
```

---

## Examples

Two runnable examples are provided:

- `cargo run --example serde_flat_json`
- `cargo run --example vector_list_ndarray`