SitePairEnergy

Trait SitePairEnergy 

Source
pub trait SitePairEnergy<S> {
    // Required method
    fn site_pair_energy(
        &self,
        site_properties_i: &S,
        site_properties_j: &S,
    ) -> f64;

    // Provided methods
    fn site_pair_energy_initial(
        &self,
        site_properties_i: &S,
        site_properties_j: &S,
    ) -> f64 { ... }
    fn is_only_infinite_or_zero() -> bool { ... }
}
Expand description

Compute the energy contribution from a pair of sites.

The SitePairEnergy trait describes a type that can compute the energy contribution from a pair of sites to the system’s total energy as a function only of those site’s properties.

The pairwise module provides a number of commonly used implementations, such as Isotropic, Anisotropic, and HardShape. Combine any of them with the PairwiseCutoff for use with MC and MD simulations or to compute system-wide properties.

The generic type names are:

§Examples

Implement a custom site energy method:

use hoomd_interaction::{
    MaximumInteractionRange, PairwiseCutoff, SitePairEnergy, TotalEnergy,
};
use hoomd_microstate::{
    Body, Microstate,
    property::{Point, Position},
};
use hoomd_vector::{Cartesian, InnerProduct};

#[derive(MaximumInteractionRange)]
struct Custom {
    epsilon: f64,
    maximum_interaction_range: f64,
}

impl<S> SitePairEnergy<S> for Custom
where
    S: Position<Position = Cartesian<2>>,
{
    fn site_pair_energy(
        &self,
        site_properties_i: &S,
        site_properties_j: &S,
    ) -> f64 {
        self.epsilon
            * site_properties_i
                .position()
                .dot(&site_properties_j.position())
    }
}

let mut microstate = Microstate::new();
microstate.extend_bodies([
    Body::point(Cartesian::from([1.0, 0.0])),
    Body::point(Cartesian::from([0.0, 1.0])),
])?;

let custom = Custom {
    epsilon: 1.0,
    maximum_interaction_range: 2.5,
};
let site_pair_energy = custom.site_pair_energy(
    &microstate.sites()[0].properties,
    &microstate.sites()[1].properties,
);

let custom = PairwiseCutoff(custom);
let total_energy = custom.total_energy(&microstate);

Implement a custom site overlap method:

use hoomd_interaction::{
    MaximumInteractionRange, PairwiseCutoff, SitePairEnergy, TotalEnergy,
};
use hoomd_microstate::{
    Body, Microstate, Transform,
    property::{Point, Position},
};
use hoomd_utility::valid::PositiveReal;
use hoomd_vector::{Cartesian, Metric};

#[derive(Default, Position)]
struct CircleSiteProperties {
    position: Cartesian<2>,
    radius: PositiveReal,
}

impl Transform<CircleSiteProperties> for Point<Cartesian<2>> {
    fn transform(
        &self,
        site_properties: &CircleSiteProperties,
    ) -> CircleSiteProperties {
        CircleSiteProperties {
            position: self.position + site_properties.position,
            ..*site_properties
        }
    }
}

#[derive(MaximumInteractionRange)]
struct PolydisperseCircleOverlap {
    maximum_interaction_range: f64,
}

impl SitePairEnergy<CircleSiteProperties> for PolydisperseCircleOverlap {
    fn site_pair_energy(
        &self,
        a: &CircleSiteProperties,
        b: &CircleSiteProperties,
    ) -> f64 {
        let r = a.position().distance(b.position());

        if r < a.radius.get() + b.radius.get() {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }

    fn site_pair_energy_initial(
        &self,
        _a: &CircleSiteProperties,
        _b: &CircleSiteProperties,
    ) -> f64 {
        0.0
    }
}

let mut microstate = Microstate::new();
microstate.extend_bodies([
    Body {
        properties: Point::new(Cartesian::from([0.0, 0.0])),
        sites: vec![CircleSiteProperties {
            position: Cartesian::from([0.0, 0.0]),
            radius: 0.5.try_into()?,
        }],
    },
    Body {
        properties: Point::new(Cartesian::from([1.4, 0.0])),
        sites: vec![CircleSiteProperties {
            position: Cartesian::from([0.0, 0.0]),
            radius: 1.0.try_into()?,
        }],
    },
])?;

let overlap = PolydisperseCircleOverlap {
    maximum_interaction_range: 1.5,
};
let site_pair_energy = overlap.site_pair_energy(
    &microstate.sites()[0].properties,
    &microstate.sites()[1].properties,
);
assert_eq!(site_pair_energy, f64::INFINITY);

let pairwise_cutoff = PairwiseCutoff(overlap);
let total_energy = pairwise_cutoff.total_energy(&microstate);
assert_eq!(total_energy, f64::INFINITY);

§Derive macro

Use the SitePairEnergy derive macro to automatically implement the SitePairEnergy trait on a type. The implemented site_pair_energy sums the result of site_pair_energy over all fields. The implementation returns early when any one field returns infinity. The implemented site_pair_energy_initial behaves similarly. The derived is_only_infinite_or_zero returns true only when all fields also return true for the same method.

use hoomd_interaction::{
    MaximumInteractionRange, SitePairEnergy,
    pairwise::{AngularMask, Anisotropic, HardSphere},
    univariate::Boxcar,
};
use hoomd_vector::Cartesian;

#[derive(MaximumInteractionRange, SitePairEnergy)]
struct SitePairInteraction {
    hard_disk: HardSphere,
    angular_mask: Anisotropic<AngularMask<Boxcar, Cartesian<2>>>,
}

Required Methods§

Source

fn site_pair_energy(&self, site_properties_i: &S, site_properties_j: &S) -> f64

Evaluate the energy contribution from a pair of sites.

Provided Methods§

Source

fn site_pair_energy_initial( &self, site_properties_i: &S, site_properties_j: &S, ) -> f64

Evaluate the energy contribution from a pair of sites in the initial state.

Override this method in potentials that have both infinite or zero terms and finite terms, such as the sum of a hard site-wall interaction plus an attractive well. site_pair_energy should compute both terms and site_pair_energy_initial should compute only the finite terms.

PairwiseCutoff calls site_pair_energy_initial when evaluating the energy of the initial state in a trial move. The infinite interaction term can be assumed 0 in the initial state because no site will ever be placed in an infinite energy configuration.

Source

fn is_only_infinite_or_zero() -> bool

Does this potential only ever return infinity or zero?

Override this method and return true for e.g. hard particle interactions that always return infinity or zero and never any other value. When this method returns true, PairwiseCutoff skips the initial energy computation and assumes it is zero.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<G, S, R, P> SitePairEnergy<S> for HardShape<G>
where S: Position<Position = P> + Orientation<Rotation = R>, G: IntersectsAtGlobal<G, P, R>,

Source§

impl<P, R, S, E> SitePairEnergy<S> for Anisotropic<E>
where S: Position<Position = P> + Orientation<Rotation = R>, P: Vector, R: Rotation + Rotate<P>, E: AnisotropicEnergy<P, R>,

Source§

impl<P, S, E> SitePairEnergy<S> for Isotropic<E>
where S: Position<Position = P>, P: Metric, E: UnivariateEnergy,

Source§

impl<S, P> SitePairEnergy<S> for HardSphere
where S: Position<Position = P>, P: Metric,