hoomd_microstate/property.rs
1// Copyright (c) 2024-2026 The Regents of the University of Michigan.
2// Part of hoomd-rs, released under the BSD 3-Clause License.
3
4//! Traits that describe body and/or site properties a a selection types that implement them.
5//!
6//! See the [crate-level documentation](crate) for an overview of how body and site
7//! properties interact with [`Microstate`](crate::Microstate) and model methods.
8//!
9//! # Provided types
10//!
11//! The structs provided in `property` may be used as [`Body`](crate::Body) and/or
12//! [`Site`](crate::Site) properties.
13//!
14//! [`Point`] represents a position in space:
15//! ```
16//! use hoomd_microstate::property::Point;
17//! use hoomd_vector::Cartesian;
18//!
19//! let point = Point::new(Cartesian::from([1.0, -3.0]));
20//! ```
21//!
22//! [`OrientedPoint`] contains both the position and orientation of an extended body:
23//! ```
24//! use hoomd_microstate::property::OrientedPoint;
25//! use hoomd_vector::{Angle, Cartesian};
26//!
27//! let point = OrientedPoint {
28//! position: Cartesian::from([1.0, -3.0]),
29//! orientation: Angle::from(1.2),
30//! };
31//! ```
32//!
33//! [`DynamicPoint`] is a point in space with mass and momentum:
34//! ```
35//! use hoomd_microstate::property::DynamicPoint;
36//! use hoomd_vector::Cartesian;
37//!
38//! let dynamic_point = DynamicPoint {
39//! position: Cartesian::from([1.0, -3.0]),
40//! momentum: Cartesian::from([-1.0, 2.0]),
41//! mass: 0.5,
42//! ..Default::default()
43//! };
44//! ```
45//!
46//! [`DynamicOrientedPoint`] is an extended body with position, orientation, mass, momentum,
47//! a moment of inertia, and angular momentum:
48//! ```
49//! use hoomd_microstate::property::DynamicOrientedPoint;
50//! use hoomd_vector::{Angle, Cartesian};
51//! use std::f64::consts::PI;
52//!
53//! let dynamic_point = DynamicOrientedPoint {
54//! position: Cartesian::from([1.0, -3.0]),
55//! orientation: Angle::from(PI / 4.0),
56//! momentum: Cartesian::from([-1.0, 2.0]),
57//! mass: 0.5,
58//! moment_of_inertia: 2.0,
59//! angular_momentum: 1.5,
60//! ..Default::default()
61//! };
62//! ```
63//!
64//! Use the `Point`, `OrientedPoint` or a custom type to represent interaction sites.
65//! `Point` and `OrientedPoint` can also be used for body properties in Monte Carlo simulations.
66//! Use the `Dynamic` variants for body properties in molecular dynamics simulations.
67//!
68//! # Custom property types
69//!
70//! When none of the provided types meets your needs, you can define a custom type.
71//! You must implement [`Position`] for your type and may implement other
72//! property traits as needed by your model.
73//!
74//! For example, this `Custom` type implements [`Position`], [`Orientation`],
75//! and has a `custom` field. The full site properties type is available when
76//! hoomd-rs computes interactions on sites, so you can use the custom fields
77//! in your own custom interaction potentials.
78//!
79//! ```
80//! use hoomd_microstate::property::{Orientation, Position};
81//! use hoomd_vector::{Cartesian, Versor};
82//!
83//! #[derive(Position, Orientation)]
84//! struct Custom {
85//! position: Cartesian<3>,
86//! orientation: Versor,
87//! custom: f64,
88//! }
89//! ```
90//!
91//! ## Transformations
92//!
93//! Implement `Transform` to take sites from the body frame to the system frame.
94//! Typically, this involves transforming position and orientation while leaving
95//! all other fields unchanged. The three most common implementations of `Transform`
96//! follow. All these examples are in 3D. To convert to 2D, replace `Cartesian<3>`
97//! with `Cartesian<2>` and `Versor` with `Angle`.
98//!
99//! Non-oriented bodies and sites (i.e. point particles or non-rotating rigid bodies):
100//! ```
101//! use hoomd_microstate::{
102//! Transform,
103//! property::{Point, Position},
104//! };
105//! use hoomd_vector::Cartesian;
106//!
107//! #[derive(Position)]
108//! struct Custom {
109//! position: Cartesian<3>,
110//! custom: f64,
111//! }
112//!
113//! impl Transform<Custom> for Point<Cartesian<3>> {
114//! fn transform(&self, site_properties: &Custom) -> Custom {
115//! Custom {
116//! position: self.position + site_properties.position,
117//! ..*site_properties
118//! }
119//! }
120//! }
121//! ```
122//!
123//! Oriented bodies and non-oriented sites (i.e. rotating rigid bodies with
124//! isotropic site-site interactions):
125//! ```
126//! use hoomd_microstate::{
127//! Transform,
128//! property::{OrientedPoint, Position},
129//! };
130//! use hoomd_vector::{Cartesian, Rotate, Rotation, Versor};
131//!
132//! #[derive(Position)]
133//! struct Custom {
134//! position: Cartesian<3>,
135//! custom: f64,
136//! }
137//!
138//! impl Transform<Custom> for OrientedPoint<Cartesian<3>, Versor> {
139//! fn transform(&self, site_properties: &Custom) -> Custom {
140//! Custom {
141//! position: self.position
142//! + self.orientation.rotate(&site_properties.position),
143//! ..*site_properties
144//! }
145//! }
146//! }
147//! ```
148//!
149//! Oriented bodies and oriented sites (i.e. rotating rigid bodies with
150//! anisotropic site-site interactions):
151//! ```
152//! use hoomd_microstate::{
153//! Transform,
154//! property::{Orientation, OrientedPoint, Position},
155//! };
156//! use hoomd_vector::{Cartesian, Rotate, Rotation, Versor};
157//!
158//! #[derive(Position, Orientation)]
159//! struct Custom {
160//! position: Cartesian<3>,
161//! orientation: Versor,
162//! custom: f64,
163//! }
164//!
165//! impl Transform<Custom> for OrientedPoint<Cartesian<3>, Versor> {
166//! fn transform(&self, site_properties: &Custom) -> Custom {
167//! Custom {
168//! position: self.position
169//! + self.orientation.rotate(&site_properties.position),
170//! orientation: self
171//! .orientation
172//! .combine(&site_properties.orientation),
173//! ..*site_properties
174//! }
175//! }
176//! }
177//! ```
178
179mod point;
180pub use point::Point;
181
182mod oriented_point;
183pub use oriented_point::OrientedPoint;
184
185mod dynamic_point;
186pub use dynamic_point::DynamicPoint;
187
188mod dynamic_oriented_point;
189pub use dynamic_oriented_point::DynamicOrientedPoint;
190
191mod oriented_hyperbolic_point;
192pub use oriented_hyperbolic_point::OrientedHyperbolicPoint;
193
194pub use hoomd_derive::{Orientation, Position};
195
196/// Locate a site or body in space: $` \vec{r} `$
197///
198/// When applied to body properties, [`Position`] describes the location of the body
199/// relative to the origin of the system coordinate system.
200///
201/// When applied to site properties, [`Position`] has a context-dependent definition.
202/// * Elements in [`Microstate::sites`] have a position located in the system frame.
203/// * Elements in [`Body::sites`] have a position located in the body frame.
204///
205/// [`Body::Sites`]: crate::Body::sites
206/// [`Microstate::sites`]: crate::Microstate::sites
207///
208/// # Units
209///
210/// Position vectors have units of $`[\mathrm{length}]`$.
211///
212/// # Derive macro
213///
214/// Use the [`Position`](macro@Position) derive macro to automatically implement
215/// the `Position` trait on a type. The type **must** have a field named `position`.
216/// ```
217/// use hoomd_microstate::property::Position;
218/// use hoomd_vector::Cartesian;
219///
220/// #[derive(Position)]
221/// struct Custom {
222/// position: Cartesian<3>,
223/// }
224/// ```
225pub trait Position {
226 /// Every position is located in this vector space.
227 type Position;
228
229 /// The position of this body or site $`[\mathrm{length}]`$.
230 fn position(&self) -> &Self::Position;
231
232 /// The mutable position of this body or site $`[\mathrm{length}]`$.
233 fn position_mut(&mut self) -> &mut Self::Position;
234}
235
236/// The translational motion of a body: $` \vec{p} `$
237///
238/// [`Momentum`] describes the translational motion of the body relative to the origin of the
239/// system coordinate system.
240///
241/// `hoomd_md` does not compute or utilize the momentum of sites.
242///
243/// # Units
244///
245/// Momentum vectors have units of $`[ \mathrm{energy}^{1/2} \cdot \mathrm{mass}^{1/2}]`$.
246pub trait Momentum {
247 /// Type that can express momentum and velocity.
248 type Momentum;
249
250 /// The momentum of this body $`[ \mathrm{energy}^{1/2} \cdot \mathrm{mass}^{1/2}]`$.
251 fn momentum(&self) -> &Self::Momentum;
252
253 /// The mutable momentum of this body $`[ \mathrm{energy}^{1/2} \cdot \mathrm{mass}^{1/2}]`$.
254 fn momentum_mut(&mut self) -> &mut Self::Momentum;
255
256 /// The velocity of this body $`[ \mathrm{energy}^{1/2} \cdot \mathrm{mass}^{-1/2}]`$.
257 fn velocity(&self) -> Self::Momentum;
258
259 /// Change the velocity of this body.
260 fn set_velocity(&mut self, velocity: Self::Momentum);
261}
262
263/// The total force acting on a site or body: $` \vec{F} `$
264///
265/// [`NetForce`] is set only for bodies that belong to a microstate. It is always in the
266/// system frame.
267///
268/// `hoomd_md` does not store the net force acting on individual sites. Use methods in
269/// `hoomd_interaction` to compute forces on sites when needed.
270///
271/// # Units
272///
273/// Net force vectors have units of $`[\mathrm{energy} \cdot \mathrm{length}^{-1}]`$.
274pub trait NetForce {
275 /// Force vector type.
276 type NetForce;
277
278 /// The net force on this body $`[\mathrm{energy} \cdot \mathrm{length}^{-1}]`$.
279 fn net_force(&self) -> &Self::NetForce;
280
281 /// The mutable net force on this body $`[\mathrm{energy} \cdot \mathrm{length}^{-1}]`$.
282 fn net_force_mut(&mut self) -> &mut Self::NetForce;
283}
284
285/// The total virial acting on a site or body: $` \mathbf{W} `$
286///
287/// [`NetVirial`] is set only for bodies that belong to a microstate. It is always in the
288/// system frame.
289///
290/// `hoomd_md` does not store the net virial acting on individual sites. Use methods in
291/// `hoomd_interaction` to compute virials on sites when needed.
292///
293/// # Units
294///
295/// Net virial matrices have units of $`[\mathrm{energy}`$.
296pub trait NetVirial {
297 /// Virial vector type.
298 type NetVirial;
299
300 /// The net virial on this body $`[\mathrm{energy}]`$.
301 fn net_virial(&self) -> &Self::NetVirial;
302
303 /// The mutable net virial on this body $`[\mathrm{energy}]`$.
304 fn net_virial_mut(&mut self) -> &mut Self::NetVirial;
305}
306
307/// The orientation of a site or body: $` \theta `$ or $` \mathbf{q} `$.
308///
309/// When applied to site properties, [`Orientation`] has a context-dependent definition.
310/// * Elements in [`Microstate::sites`] describe the rotation from the site's local frame
311/// to the system frame.
312/// * Elements in [`Body::sites`] describe the rotation from the site's local frame to the
313/// body frame.
314///
315/// When applied to body properties, [`Orientation`] describes the rotation from
316/// the body frame to the system frame.
317///
318/// [`Body::Sites`]: crate::Body::sites
319/// [`Microstate::sites`]: crate::Microstate::sites
320///
321/// # Units
322///
323/// The units of [`Orientation`] depend on the representation chosen for `Rotation`.
324/// For example, [`hoomd_vector::Angle`] has units of radians while
325/// [`hoomd_vector::Versor`] is unitless.
326///
327/// # Derive macro
328///
329/// Use the [`Orientation`](macro@Orientation) derive macro to automatically implement
330/// the `Orientation` trait on a type. The type **must** have a field named `orientation`.
331/// ```
332/// use hoomd_microstate::property::Orientation;
333/// use hoomd_vector::Versor;
334///
335/// #[derive(Orientation)]
336/// struct Custom {
337/// orientation: Versor,
338/// }
339/// ```
340pub trait Orientation {
341 /// Type that can express the orientation of a site or body.
342 type Rotation;
343
344 /// The orientation of this site or body.
345 fn orientation(&self) -> &Self::Rotation;
346
347 /// The orientation of this site or body (mutable).
348 fn orientation_mut(&mut self) -> &mut Self::Rotation;
349}
350
351/// A body's resistance to change in translational motion: $` m `$
352///
353/// [`Mass`] connects a body's linear momentum to its linear velocity: $` \vec{p} = m \vec{v} `$.
354///
355/// `hoomd_md` does not compute or utilize the mass of sites.
356///
357/// # Units
358///
359/// The units of [`Mass`] are $` [\mathrm{mass}] `$.
360pub trait Mass {
361 /// The mass of this body $` [\mathrm{mass}] `$.
362 fn mass(&self) -> f64;
363}
364
365/// A body's resistance to a change in rotational motion: $` I `$
366///
367/// [`MomentOfInertia`] connects a body's angular momentum to its angular velocity:
368/// $` \vec{L} = I \vec{\omega} `$.
369///
370/// `hoomd_md` does not compute or utilize the moment of inertia of sites.
371///
372/// # Units
373///
374/// The units of [`MomentOfInertia`] are $` [\mathrm{mass} \cdot \mathrm{length}^2] `$.
375pub trait MomentOfInertia {
376 /// Type that expresses the moment of inertia.
377 type MomentOfInertia;
378
379 /// The moment of inertia of this body $` [\mathrm{mass} \cdot \mathrm{length}^2] `$.
380 fn moment_of_inertia(&self) -> &Self::MomentOfInertia;
381
382 /// The mutable moment of inertia of this body $` [\mathrm{mass} \cdot \mathrm{length}^2] `$.
383 fn moment_of_inertia_mut(&mut self) -> &mut Self::MomentOfInertia;
384}
385
386/// The rotational motion of a body: $` \vec{L} `$
387///
388/// [`AngularMomentum`] describes the rotational motion of the body in the *body* frame.
389///
390/// `hoomd_md` does not compute or utilize the angular momentum of sites.
391///
392/// # Units
393///
394/// The units of [`AngularMomentum`] are $` [\mathrm{mass}^{1/2} \cdot \mathrm{length} \cdot \mathrm{energy}^{1/2}] `$.
395pub trait AngularMomentum {
396 /// Type that can express the angular momentum of a site or body.
397 type AngularMomentum;
398
399 /// The angular momentum of this site or body $` [\mathrm{mass}^{1/2} \cdot \mathrm{length} \cdot \mathrm{energy}^{1/2}] `$.
400 fn angular_momentum(&self) -> &Self::AngularMomentum;
401
402 /// The mutable angular momentum of this site or body $` [\mathrm{mass}^{1/2} \cdot \mathrm{length} \cdot \mathrm{energy}^{1/2}] `$.
403 fn angular_momentum_mut(&mut self) -> &mut Self::AngularMomentum;
404}
405
406/// The total torque acting on a body: $` \vec{\tau} `$
407///
408/// [`NetTorque`] is set only for bodies that belong to a microstate. It is always in the
409/// system frame.
410///
411/// `hoomd_md` does not store the net force acting on individual sites. Use methods in
412/// `hoomd_interaction` to compute torques on sites when needed.
413///
414/// # Units
415///
416/// The units of [`NetTorque`] are $` [\mathrm{energy}] `$.
417pub trait NetTorque {
418 /// Type that can express the net torque on a site or body.
419 type NetTorque;
420
421 /// The net torque on this site or body $` [\mathrm{energy}] `$.
422 fn net_torque(&self) -> &Self::NetTorque;
423
424 /// The mutable net torque on this site or body $` [\mathrm{energy}] `$.
425 fn net_torque_mut(&mut self) -> &mut Self::NetTorque;
426}
427
428/// Moment of inertia and angular momentum types.
429///
430/// [`RotationalMotionTypes`] sets which structs store the moment of inertia
431/// and angular momentum for a given `Rotation` representation.
432pub trait RotationalMotionTypes {
433 /// Type that stores the moment of inertia in the natural coordinate frame of the body's local rotation.
434 type MomentOfInertia;
435 /// Type that stores the angular momentum.
436 type AngularMomentum;
437}