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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//! `AtomRestraint` trait and concrete soft-penalty types for molecular packing.
//!
//! Each `*Restraint` struct is a **concrete, independent type** holding its own
//! geometric parameters — no `Builtin*` wrapper, no tagged-union `{kind, params[9]}`
//! blob, no builder pattern. User extensions `impl AtomRestraint` identically and sit
//! beside the 14 Packmol-originals in type space.
//!
//! Numerical equivalence to the Fortran `comprest.f90` (value) and `gwalls.f90`
//! (gradient) is preserved branch-for-branch; see `docs/packmol_parity.md`.
//!
//! **Gradient convention**: `AtomRestraint::fg` accumulates INTO `g` with `+=`.
//! Do not overwrite; many restraints may contribute to the same atom.
//!
//! **Two-scale contract** (Packmol convention): linear penalties
//! (box / cube / plane, kinds 2/3/6/7/10/11) use `scale`; quadratic penalties
//! (sphere / ellipsoid / cylinder / gaussian, kinds 4/5/8/9/12/13/14/15) use
//! `scale2`. Each `impl AtomRestraint` decides internally which to consume.
//!
//! Direction-3 rule (see spec §0 bullet 9): all molrs-pack extension points
//! follow `pub trait X` + N concrete pub structs that `impl X`; user-defined
//! structs `impl X` the same way. No `Builtin*` prefix, no wrapper, no builder.
use F;
// ============================================================================
// Trait
// ============================================================================
/// Soft-penalty restraint evaluated per atom during packing.
///
/// - `f` — value only (line-search interpolation)
/// - `fg` — fused value + gradient; gradient accumulates INTO `g` with `+=`
/// - `is_parallel_safe` — if `false`, scheduler serializes this restraint
/// (Python-backed restraints MUST return `false`)
/// - `name` — human-readable identifier (default: `std::any::type_name::<Self>()`)
/// - `periodic_box` — opt-in: a restraint may declare that it defines a
/// periodic axis-aligned box (`min`, `max`, `periodic[k]` per axis).
/// At most one periodic box may be declared across all restraints on a
/// packing run; the packer resolves multiple declarations by requiring
/// identical bounds. Default `None` (non-periodic); only
/// [`InsideBoxRestraint`] overrides it.
///
/// `Debug` is required on concrete impls so `Target` / `Molpack` remain
/// printable for diagnostics. All built-in restraints derive it; user types
/// should do the same.
/// Blanket impl so `Box<dyn AtomRestraint>` itself implements the trait.
pub use ;
pub use ;