| Crates.io | mesh-sieve |
| lib.rs | mesh-sieve |
| version | 2.0.0 |
| created_at | 2025-06-12 22:09:40.733356+00 |
| updated_at | 2025-09-15 06:11:23.868196+00 |
| description | Modular, high-performance Rust library for mesh and data management, designed for scientific computing and PDE codes. |
| homepage | https://github.com/tmathis720/mesh-sieve |
| repository | https://github.com/tmathis720/mesh-sieve |
| max_upload_size | |
| id | 1710763 |
| size | 6,238,400 |
mesh-sieve is a modular, high-performance Rust library for mesh topology and field data. It powers refinement/assembly pipelines and overlap-driven exchange for serial, threaded, and MPI-distributed workflows. The APIs are Result-first (no hidden panics), invariants are easy to validate (strict-invariants), and the data layer is storage-generic (CPU Vec by default; optional wgpu backend).
Section<V, S> where S: SliceStorage<V> (built-in VecStorage; optional WgpuStorage with compute kernels).NoComm, in-process RayonComm, feature-gated MpiComm).cargo build
cargo run
Enable only what you need:
[dependencies]
mesh-sieve = { version = "2", features = [
# safety & determinism
# "strict-invariants", # deep invariant checks in debug/CI
# "deterministic-order", # stable BTree maps/sets for IO/repro
# "fast-hash", # AHash maps/sets for speed (non-deterministic order)
# parallel & distributed
# "rayon", # parallel refine/assemble utilities
# "mpi-support", # MPI communicator backend
# partitioning
# "metis-support", # METIS bindings
# data adapters
# "map-adapter", # legacy infallible helpers (panic-on-miss)
# GPU
# "wgpu", # WgpuStorage for Section (V: Pod + Zeroable)
] }
CI tip: run a lane with
--features strict-invariantsto catch structural and mirror mistakes early, even in optimized builds.
use mesh_sieve::topology::sieve::{InMemorySieve, Sieve};
use mesh_sieve::topology::point::PointId;
let mut g = InMemorySieve::<PointId, ()>::default();
let a = PointId::new(1)?; let b = PointId::new(2)?;
g.add_arrow(a, b, ());
for v in g.cone_points(a) { /* point-only: no payload clones */ }
let reach: Vec<_> = g.closure_iter([a]).collect();
use mesh_sieve::data::atlas::Atlas;
use mesh_sieve::data::slice_storage::VecStorage;
use mesh_sieve::data::section::Section;
use mesh_sieve::topology::point::PointId;
let mut atlas = Atlas::default();
let p = PointId::new(7)?;
atlas.try_insert(p, 3)?;
let mut sec = Section::<f64, VecStorage<f64>>::new(atlas);
sec.try_set(p, &[1.0, 2.0, 3.0])?;
let s = sec.try_restrict(p)?; // &[f64]
use mesh_sieve::data::bundle::{Bundle, AverageReducer};
use mesh_sieve::topology::stack::InMemoryStack;
let mut bundle: Bundle<f64> = Bundle {
stack: InMemoryStack::new(), // base -> cap (Polarity payload)
section: /* Section<f64, _> */,
delta: mesh_sieve::overlap::delta::CopyDelta,
};
// Refinement (base -> cap) with orientation-aware slice transforms:
bundle.refine([/* base points */])?;
// Assembly (cap -> base) with explicit reduction; lengths checked up-front:
bundle.assemble_with([/* base points */], &AverageReducer)?;
use mesh_sieve::overlap::overlap::Overlap;
use mesh_sieve::topology::point::PointId;
let mut ov = Overlap::default();
let p = PointId::new(42)?;
let neighbor = 1usize;
let inserted = ov.add_link_structural_one(p, neighbor); // remote unknown yet
// Later:
ov.resolve_remote_point(p, neighbor, PointId::new(42042)?)?;
# build with MPI
cargo run --features mpi-support --example mpi_complete
# or:
mpirun -n 2 cargo run --features mpi-support --example mpi_complete
More examples:
mpi_complete.rs, mpi_complete_stack.rs: section/stack completionmesh_distribute_two_ranks.rs: distributing a meshmpi_complete_multiple_neighbors.rs: multi-neighbor exchangesrc/
topology/ # Sieve & traversal, strata, lattice
data/ # Atlas, Section, storage backends (Vec/WGPU), deltas, helpers
overlap/ # Overlap graph, value deltas, perf types
algs/ # communicators, completion, distribute, partition utilities
partitioning/ # METIS integration + in-tree algorithms
...
Breaking (safer)
insert, restrict, restrict_mut, set, get, get_mut) are removed or gated. Prefer try_*.Atlas::remove_point(p) now returns Err(MissingAtlasPoint(p)) if absent.Section::with_atlas_mut rejects length changes for existing points. Use with_atlas_mut_resize(..., ResizePolicy) when resizing is intended.Orientation → Polarity (renamed). The old alias is deprecated.Data/Storage
Section<V, S> is generic over storage (S: SliceStorage<V>):
VecStorage (CPU) for any V: Clone + DefaultWgpuStorage (feature wgpu) for V: bytemuck::Pod + ZeroableScatterPlan { atlas_version, spans } is a stable contract; plans are refused if versions diverge.
Fast-path scatter: if spans are contiguous and buffer lengths match, we do a single clone_from_slice.
Overlap
Stronger invariants in validate_invariants():
check-empty-part)strict-invariants): counts, endpoints and payloads must match exactly.Performance & Determinism
Bundle::{refine, assemble_with} (no per-base heap churn).reserve_cone, reserve_support).Atlas::get, Section::try_restrict(_mut)).fast-hash for speed or deterministic-order for reproducible iteration.Error Hygiene
PointIds in errors.AtlasPointLengthChanged { point, old_len, new_len }, AtlasPlanStale, strict overlap mirror errors).| Area | Key APIs |
|---|---|
| Sieve | cone(_)/support(_), cone_points(_)/support_points(_), closure_iter, star_iter |
| Atlas | try_insert, get, remove_point, points, atlas_map, version, invariants |
| Section | new, try_restrict(_)/try_restrict_mut(_), try_set, with_atlas_mut, with_atlas_mut_resize, try_scatter_*, try_apply_delta_between_points |
| Storage | VecStorage, (opt-in) WgpuStorage (delta via copy/compute) |
| Deltas | data::refine::SliceDelta (slice→slice; e.g., Polarity), overlap::ValueDelta (comm/merge; e.g., CopyDelta, AddDelta, ZeroDelta) |
| Overlap | add_link_structural_one, add_links_structural_bulk, resolve_remote_point(s), ensure_closure_of_support |
| Bundles | refine(bases), assemble_with(bases, &Reducer) |
| Algs | completion for sieve/section/stack; communicator trait & backends |
Legacy infallible helpers (
restrict_closure,restrict_star, etc.) and theMapadapter are gated behindfeature = "map-adapter". PreferFallibleMap+try_*helpers.
wgpu)Use Section<V, WgpuStorage<V>> with V: bytemuck::Pod + Zeroable.
Delta routing:
Polarity::Forward → copy_buffer_to_bufferPolarity::Reverse → tiny reverse_copy.wgsl compute kernel (or equivalent)SliceDelta → dedicate small compute pipelinesScatter validates ScatterPlan.atlas_version vs Atlas::version() before encoding commands.
#[cfg(feature = "wgpu")]
{
use mesh_sieve::data::{atlas::Atlas, section::Section};
use mesh_sieve::data::wgpu::WgpuStorage;
let atlas = /* ... */;
let storage = WgpuStorage::<f32>::new(device.clone(), &atlas)?;
let mut sec = Section::<f32, WgpuStorage<f32>>::from_storage(atlas, storage);
// Version-checked scatter:
let plan = sec.atlas().build_scatter_plan();
sec.try_scatter_with_plan(&host_values, &plan)?;
}
*_iter) and point-only adapters (cone_points, support_points) in hot paths.reserve_cone / reserve_support before bulk updates.fast-hash for speed or deterministic-order for stable I/O and tests.Property tests for Atlas/Section coherence (random insert/remove/shuffle + validate_invariants + scatter/gather round-trip).
Delta aliasing tests (overlap/disjoint) to ensure no panics.
Parallel determinism (with rayon) for refine/assemble parity.
CI lane with:
cargo test --features strict-invariants
Panicking data APIs removed/gated
insert/restrict/restrict_mut/set/get/get_mut → try_* equivalents.map-adapter to keep legacy helpers while you refactor.with_atlas_mut is strict
AtlasPointLengthChanged.with_atlas_mut_resize(|atlas| { ... }, ResizePolicy::PreservePrefix|PreserveSuffix|Reinit) for explicit resizes.Orientation → Polarity
Overlap mirror checks (strict)
adjacency_* directly, switch to API mutators. Strict mode verifies in/out symmetry and payload equality.MIT — see LICENSE.