1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Particle insertion: random, rate-based, and file-based from `[[particles.insert]]` config.
//!
//! # Parallel insertion model (born-in-owner)
//!
//! Insertion is **not** done on one rank and scattered. Instead it runs on
//! *every* MPI rank, and every rank seeds its RNG with the **same** `seed`, so
//! all ranks generate the bit-identical candidate stream — the same positions,
//! radii, velocities, and tags, in the same order. Each rank then keeps **only**
//! the candidates whose position falls inside its own subdomain, tested with a
//! half-open interval (`low ≤ pos < high`, via the `owns_position` helper) that matches
//! `Domain::exchange()` ownership exactly.
//!
//! Three properties follow:
//!
//! - **Born in its owner.** Each atom is materialized only on the rank that owns
//! its position, so the first post-insertion `exchange()` never has to migrate
//! it — no insertion-time communication is needed.
//! - **Exactly-once.** The half-open convention guarantees every position is
//! claimed by one rank, never two and never zero (no duplicated or dropped
//! atoms at subdomain boundaries).
//! - **Deterministic across rank counts.** Because the candidate stream depends
//! only on `seed` (not on the decomposition), the *global* packing is
//! identical whether you run on 1 rank or 64 — only the partitioning of that
//! packing changes. Overlap rejection uses a global spatial hash replicated on
//! every rank, so packings are reproducible run-to-run and rank-count to
//! rank-count.
//!
//! File-based insertion follows the same rule: the file is parsed on every rank
//! and filtered to the local subdomain, with tags advanced identically so they
//! stay globally consistent.
use HashMap;
use PI;
use fmt;
use File;
use ;
use *;
use *;
use StdRng;
use SeedableRng;
use ;
use Deserialize;
use CurrentState;
use ;
use crate::;
// ── Particle insertion ─────────────────────────────────────────────────────
use *;
use *;
use *;
use *;
pub use ;
pub use dem_insert_atoms;
pub use dem_rate_insert;
pub use DemAtomInsertPlugin;