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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
//! # Physics Interface Traits
//!
//! Defines the core trait abstractions for potential energy computations.
//! Different interaction types have specialized signatures optimized for
//! their specific computational patterns.
//!
//! ## Trait Hierarchy
//!
//! - [`Potential2`]: 2-body interactions (pairs, bonds)
//! - [`Potential3`]: 3-body interactions (angles)
//! - [`Potential4`]: 4-body interactions (torsions, impropers)
//!
//! ## Design Philosophy
//!
//! ### Raw Derivatives
//!
//! Potentials return "raw" derivatives rather than Cartesian forces:
//!
//! - **2-Body**: Returns force factor `S = -(dV/dr) / r`
//! - Actual force: `F_vec = S * r_vec`
//!
//! - **3-Body**: Returns `dV/d(cos_theta)`
//! - Caller applies chain rule for Cartesian mapping
//!
//! - **4-Body**: Returns `dV/d(phi)`
//! - Caller applies chain rule for Cartesian mapping
//!
//! This separation keeps potential implementations simple and pure mathematical,
//! while allowing the caller (force field engine) to handle coordinate transformations.
use crateVector;
// ============================================================================
// 2-Body Potential (Pair & Bond)
// ============================================================================
/// Two-body potential energy function.
///
/// Used for both non-bonded pair interactions (LJ, Coulomb) and
/// bonded stretch interactions (harmonic, Morse).
///
/// ## Input Convention
///
/// All methods accept `r_sq` (squared distance) rather than `r` to avoid
/// unnecessary square root operations in the common case.
///
/// ## Force Factor Convention
///
/// The `force_factor` method returns:
///
/// ```text
/// S = -(dV/dr) / r = -dV/d(r^2) * 2
/// ```
///
/// To obtain the force vector from particle j to particle i:
///
/// ```text
/// F_ij = S * r_ij_vec
/// ```
///
/// where `r_ij_vec = r_i - r_j` (vector from j to i).
// ============================================================================
// 3-Body Potential (Angle)
// ============================================================================
/// Three-body angular potential energy function.
///
/// Computes energy as a function of the angle formed by three particles (i-j-k),
/// where j is the central vertex.
///
/// ## Input Convention
///
/// Methods accept:
/// - `r_ij_sq`: Squared distance i-j
/// - `r_jk_sq`: Squared distance j-k
/// - `cos_theta`: Cosine of angle i-j-k (computed from dot product)
///
/// The cosine is preferred over the angle itself because:
/// 1. It's directly available from the dot product: `cos_theta = (r_ij ยท r_jk) / (|r_ij| |r_jk|)`
/// 2. Many angle potentials (GROMOS, DREIDING) use cosine directly
/// 3. Avoids expensive `acos` operation in the common case
///
/// ## Derivative Convention
///
/// The `derivative` method returns `dV/d(cos_theta)`.
///
/// The caller is responsible for applying the chain rule to obtain
/// Cartesian forces. For angle i-j-k:
///
/// ```text
/// d(cos_theta)/d(r_i) = (r_jk/|r_jk| - cos_theta * r_ij/|r_ij|) / |r_ij|
/// ```
///
/// (and similar expressions for j and k)
// ============================================================================
// 4-Body Potential (Torsion & Improper)
// ============================================================================
/// Four-body dihedral potential energy function.
///
/// Computes energy as a function of the dihedral angle formed by four particles.
///
/// For proper torsions (i-j-k-l): phi is the angle between planes (i,j,k) and (j,k,l)
/// For improper torsions: phi typically measures out-of-plane displacement
///
/// ## Input Convention
///
/// Methods accept both `cos_phi` and `sin_phi` because:
/// 1. Both are efficiently computed from cross products
/// 2. Many potentials need `cos(n*phi)` which requires both via Chebyshev/recurrence
/// 3. The sign of `sin_phi` determines the quadrant
///
/// ## Derivative Convention
///
/// The `derivative` method returns `dV/d(phi)`.
///
/// Note: This is the derivative with respect to the angle itself, not its
/// trigonometric functions. The caller handles the chain rule:
///
/// ```text
/// dV/d(cos_phi) = -dV/d(phi) / sin_phi (where sin_phi != 0)
/// ```