hoomd_interaction/pairwise/isotropic.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//! Implement Isotropic
5
6use serde::{Deserialize, Serialize};
7
8use crate::{MaximumInteractionRange, SitePairEnergy, univariate::UnivariateEnergy};
9use hoomd_microstate::property::Position;
10use hoomd_vector::Metric;
11
12/// Compute isotropic interactions between a pair of sites.
13///
14/// [`Isotropic`] provides a single implementation that computes pairwise
15/// interactions that are a function only of the distance between sites. It
16/// fills the gap between traits like [`SitePairEnergy`] which operates on
17/// site properties and [`UnivariateEnergy`] which is a function only of the
18/// separation distance.
19///
20/// Use [`Isotropic`] with [`PairwiseCutoff`] in MD and MC simulations.
21///
22/// [`PairwiseCutoff`]: crate::PairwiseCutoff
23/// # Example
24///
25/// ```
26/// use hoomd_interaction::{
27/// SitePairEnergy, pairwise::Isotropic, univariate::LennardJones,
28/// };
29/// use hoomd_microstate::property::Point;
30/// use hoomd_vector::Cartesian;
31///
32/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
33/// let a = Point {
34/// position: Cartesian::from([0.0, 0.0]),
35/// };
36/// let b = Point {
37/// position: Cartesian::from([0.0, 2.0 * 2.0_f64.powf(1.0 / 6.0)]),
38/// };
39///
40/// let lennard_jones: LennardJones = LennardJones {
41/// epsilon: 1.5,
42/// sigma: 2.0,
43/// };
44/// let lennard_jones = Isotropic {
45/// interaction: lennard_jones,
46/// r_cut: 2.5,
47/// };
48///
49/// let energy = lennard_jones.site_pair_energy(&a, &b);
50/// assert_eq!(energy, -1.5);
51/// # Ok(())
52/// # }
53/// ```
54#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
55pub struct Isotropic<E> {
56 /// The site-site interaction.
57 pub interaction: E,
58 /// Maximum distance between two interacting sites.
59 pub r_cut: f64,
60}
61
62impl<P, S, E> SitePairEnergy<S> for Isotropic<E>
63where
64 S: Position<Position = P>,
65 P: Metric,
66 E: UnivariateEnergy,
67{
68 #[inline]
69 fn site_pair_energy(&self, site_properties_i: &S, site_properties_j: &S) -> f64 {
70 let r = site_properties_i
71 .position()
72 .distance(site_properties_j.position());
73 if r >= self.r_cut {
74 return 0.0;
75 }
76
77 self.interaction.energy(r)
78 }
79}
80
81impl<E> MaximumInteractionRange for Isotropic<E> {
82 #[inline]
83 fn maximum_interaction_range(&self) -> f64 {
84 self.r_cut
85 }
86}