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
//! The ergonomic layer: domain operations reachable as methods on a handle.
//!
//! Each submodule here declares one extension trait over [`Structure`], and
//! each trait method is a forwarder — the body it calls is the free function in
//! the facet's own module, reached by static dispatch through
//! [`Structure::engine`]. There is no vtable, no wrapper value and no second
//! implementation: `structure.atom_contacts(4.5)` and
//! `molframe::analysis::atom_contacts(structure.engine(), 4.5, backend, ctx)`
//! execute the same code, and a caller who wants the long form writes it.
//!
//! # Why the methods carry the kernel's name
//!
//! A method name is the kernel function's name, exactly, and the `_with`
//! suffix marks the form that takes the backend and the [`ExecutionContext`]
//! explicitly. Inventing a shorter alias for a method — `contacts` for
//! `atom_contacts` — would put two names on one concept, which is the drift
//! this façade exists to remove. `use molframe::prelude::*` brings the traits
//! in; the method and the function then coexist without ambiguity, because a
//! method call is not a path.
//!
//! # Which domains have a trait, and which do not
//!
//! A trait exists where the domain's kernels take a structure first:
//! [`AnalysisExt`], [`ValidationExt`] and [`CompareExt`]. [`SurfaceExt`] is the
//! one deliberate exception: surface kernels are coordinate-first, so its
//! methods are not forwarders. They gather the coordinates of one model, take
//! radii from the table the options resolve (the profile's `vdw-radii` line unless
//! one is named), and give an atom with
//! no radius a `NaN` area that does not occlude its neighbours. That policy is
//! stated once, in `surface`, instead of being rediscovered by every caller.
//! Geometry and the spatial planners stay free functions over coordinates,
//! reached with [`Selection::to_coordinates`](crate::Selection::to_coordinates)
//! and [`Structure::coordinates`](crate::Structure::coordinates).
//!
//! [`ExecutionContext`]: crate::ExecutionContext
pub use AnalysisExt;
pub use CompareExt;
pub use ;
pub use ValidationExt;