Skip to main content

External

Struct External 

Source
pub struct External<E>(pub E);
Expand description

Interactions between sites and external fields.

An External newtype wrapping a type that implements SiteEnergy represents:

U_\mathrm{total} = \sum_{i=0}^{N-1} U\left( s_i \right)

where $s_i$ is the full set of site properties for site i.

An External newtype wrapping a type that implements SiteForceAndVirial and/or SiteForceVirialAndTorque represents:

\vec{F}_i = \vec{F}\left(s_i\right)
\vec{\tau}_i = \vec{\tau}\left(s_i\right)

where $\vec{F}(s_i)$ is the force computed by SiteForceAndVirial (or SiteForceVirialAndTorque) and $\vec{\tau}(s_i)$ is the torque computed by SiteForceVirialAndTorque.

A type that implements both SiteEnergy and SiteForceAndVirial (or SiteForceVirialAndTorque) must compute forces and torques that are derivatives of the energy.

Use External with ConstantForce or your own custom type that implements SiteEnergy, SiteForceAndVirial and/or SiteForceVirialAndTorque.

§Examples

A linear external potential given by a constant force:

use hoomd_interaction::{External, TotalEnergy, external::ConstantForce};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let total_energy = constant_force.total_energy(&microstate);
assert_eq!(total_energy, 2.0);

Infinite interaction with a wall:

use hoomd_interaction::{External, SiteEnergy, TotalEnergy};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

struct Wall;

impl SiteEnergy<Point<Cartesian<2>>> for Wall {
    fn site_energy(&self, site_properties: &Point<Cartesian<2>>) -> f64 {
        if site_properties.position[1].abs() < 1.0 {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut microstate = Microstate::new();
    microstate.extend_bodies([
        Body::point(Cartesian::from([1.0, 1.25])),
        Body::point(Cartesian::from([-1.0, 2.0])),
    ])?;

    let wall = External(Wall);

    let total_energy = wall.total_energy(&microstate);
    assert_eq!(total_energy, 0.0);
    Ok(())
}

Tuple Fields§

§0: E

Trait Implementations§

Source§

impl<E: Clone> Clone for External<E>

Source§

fn clone(&self) -> External<E>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<E: Debug> Debug for External<E>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<P, B, S, X, C, E> DeltaEnergyInsert<B, S, X, C> for External<E>
where E: SiteEnergy<S>, B: Transform<S>, S: Position<Position = P>, C: Wrap<B> + Wrap<S>,

Source§

fn delta_energy_insert( &self, initial_microstate: &Microstate<B, S, X, C>, new_body: &Body<B, S>, ) -> f64

Evaluate the change in energy contributed by External when a single body is inserted.

§Examples

A linear external potential given by a constant force:

use hoomd_interaction::{
    DeltaEnergyInsert, External, external::ConstantForce,
};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let delta_energy = constant_force
    .delta_energy_insert(&microstate, &Body::point([0.0, -1.0].into()));
assert_eq!(delta_energy, -1.0);

Infinite interaction with a wall:

use hoomd_interaction::{DeltaEnergyInsert, External, SiteEnergy};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

struct Wall;

impl SiteEnergy<Point<Cartesian<2>>> for Wall {
    fn site_energy(&self, site_properties: &Point<Cartesian<2>>) -> f64 {
        if site_properties.position[1].abs() < 1.0 {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut microstate = Microstate::new();
    microstate.extend_bodies([
        Body::point(Cartesian::from([1.0, 1.25])),
        Body::point(Cartesian::from([-1.0, 2.0])),
    ])?;

    let wall = External(Wall);

    let delta_energy = wall
        .delta_energy_insert(&microstate, &Body::point([0.0, -0.5].into()));
    assert_eq!(delta_energy, f64::INFINITY);
    Ok(())
}
Source§

impl<P, B, S, X, C, E> DeltaEnergyOne<B, S, X, C> for External<E>
where E: SiteEnergy<S>, B: Transform<S>, S: Position<Position = P>, C: Wrap<B> + Wrap<S>,

Source§

fn delta_energy_one( &self, initial_microstate: &Microstate<B, S, X, C>, body_index: usize, final_body: &Body<B, S>, ) -> f64

Evaluate the change in energy contributed by External when a single body is updated.

§Examples

A linear external potential given by a constant force:

use hoomd_interaction::{
    DeltaEnergyOne, External, external::ConstantForce,
};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let delta_energy = constant_force.delta_energy_one(
    &microstate,
    0,
    &Body::point([0.0, -1.0].into()),
);
assert_eq!(delta_energy, -1.0);

Infinite interaction with a wall:

use hoomd_interaction::{DeltaEnergyOne, External, SiteEnergy};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

struct Wall;

impl SiteEnergy<Point<Cartesian<2>>> for Wall {
    fn site_energy(&self, site_properties: &Point<Cartesian<2>>) -> f64 {
        if site_properties.position[1].abs() < 1.0 {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut microstate = Microstate::new();
    microstate.extend_bodies([
        Body::point(Cartesian::from([1.0, 1.25])),
        Body::point(Cartesian::from([-1.0, 2.0])),
    ])?;

    let wall = External(Wall);

    let delta_energy = wall.delta_energy_one(
        &microstate,
        0,
        &Body::point([0.0, -0.5].into()),
    );
    assert_eq!(delta_energy, f64::INFINITY);
    Ok(())
}
Source§

impl<B, S, X, C, E> DeltaEnergyRemove<B, S, X, C> for External<E>
where E: SiteEnergy<S>,

Source§

fn delta_energy_remove( &self, initial_microstate: &Microstate<B, S, X, C>, body_index: usize, ) -> f64

Evaluate the change in energy contributed by External when a single body is removed.

§Examples

A linear external potential given by a constant force:

use hoomd_interaction::{
    DeltaEnergyRemove, External, external::ConstantForce,
};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let delta_energy = constant_force.delta_energy_remove(&microstate, 0);
assert_eq!(delta_energy, -1.0);

Infinite interaction with a wall:

use hoomd_interaction::{DeltaEnergyRemove, External, SiteEnergy};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

struct Wall;

impl SiteEnergy<Point<Cartesian<2>>> for Wall {
    fn site_energy(&self, site_properties: &Point<Cartesian<2>>) -> f64 {
        if site_properties.position[1].abs() < 1.0 {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut microstate = Microstate::new();
    microstate.extend_bodies([
        Body::point(Cartesian::from([1.0, 1.25])),
        Body::point(Cartesian::from([-1.0, 2.0])),
    ])?;

    let wall = External(Wall);

    let delta_energy = wall.delta_energy_remove(&microstate, 0);
    assert_eq!(delta_energy, 0.0);
    Ok(())
}
Source§

impl<'de, E> Deserialize<'de> for External<E>
where E: Deserialize<'de>,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<E> MaximumInteractionRange for External<E>

Source§

fn maximum_interaction_range(&self) -> f64

The largest distance between two sites where the pairwise interaction may be non-zero.
Source§

impl<V, B, S, X, C, E> NetSiteForceAndVirial<B, S, X, C> for External<E>
where V: Outer, S: Position<Position = V>, E: SiteForceAndVirial<S, Force = V>,

Source§

fn net_site_force_and_virial( &self, microstate: &Microstate<B, S, X, C>, site_index: usize, ) -> (V, V::Tensor)

Compute the net force and virial on a given site.

§Example
use hoomd_interaction::{
    External, NetSiteForceAndVirial, external::ConstantForce,
};
use hoomd_linear_algebra::matrix::Matrix;
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let (force, virial) =
    constant_force.net_site_force_and_virial(&microstate, 0);
assert_eq!(force, [0.0, -1.0].into());
assert_eq!(
    virial,
    Matrix {
        rows: [[0.0, 0.0], [-2.0, 0.0]]
    }
);
Source§

type Force = V

The type of the result force.
Source§

impl<V, B, S, X, C, E> NetSiteForceVirialAndTorque<B, S, X, C> for External<E>
where V: Wedge + Outer, S: Position<Position = V>, E: SiteForceVirialAndTorque<S, Force = V>,

Source§

fn net_site_force_virial_and_torque( &self, microstate: &Microstate<B, S, X, C>, site_index: usize, ) -> (V, V::Tensor, V::Bivector)

Compute the net force, virial, and torque on a given site.

§Example
use hoomd_interaction::{
    External, NetSiteForceVirialAndTorque, external::ConstantForce,
};
use hoomd_linear_algebra::matrix::Matrix;
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let (force, virial, torque) =
    constant_force.net_site_force_virial_and_torque(&microstate, 0);
assert_eq!(force, [0.0, -1.0].into());
assert_eq!(
    virial,
    Matrix {
        rows: [[0.0, 0.0], [-2.0, 0.0]]
    }
);
assert_eq!(torque, 0.0);
Source§

type Force = V

The type of the result force.
Source§

impl<E: PartialEq> PartialEq for External<E>

Source§

fn eq(&self, other: &External<E>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<E> Serialize for External<E>
where E: Serialize,

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl<B, S, X, C, E> TotalEnergy<Microstate<B, S, X, C>> for External<E>
where E: SiteEnergy<S>,

Source§

fn total_energy(&self, microstate: &Microstate<B, S, X, C>) -> f64

Compute the total energy of the microstate contributed by functions of a single site.

The sum over sites differs from HOOMD-blue where external energies are evaluated only at the body centers. In general, hoomd-rs interactions apply to sites. Use a custom implementation to compute energies over body centers.

§Examples

A linear external potential given by a constant force:

use hoomd_interaction::{External, TotalEnergy, external::ConstantForce};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let total_energy = constant_force.total_energy(&microstate);
assert_eq!(total_energy, 2.0);

Infinite interaction with a wall:

use hoomd_interaction::{External, SiteEnergy, TotalEnergy};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

struct Wall;

impl SiteEnergy<Point<Cartesian<2>>> for Wall {
    fn site_energy(&self, site_properties: &Point<Cartesian<2>>) -> f64 {
        if site_properties.position[1].abs() < 1.0 {
            f64::INFINITY
        } else {
            0.0
        }
    }

    fn is_only_infinite_or_zero() -> bool {
        true
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut microstate = Microstate::new();
    microstate.extend_bodies([
        Body::point(Cartesian::from([1.0, 1.25])),
        Body::point(Cartesian::from([-1.0, 2.0])),
    ])?;

    let wall = External(Wall);

    let total_energy = wall.total_energy(&microstate);
    assert_eq!(total_energy, 0.0);
    Ok(())
}
Source§

fn delta_energy_total( &self, initial_microstate: &Microstate<B, S, X, C>, final_microstate: &Microstate<B, S, X, C>, ) -> f64

Compute the difference in energy between two microstates.

Returns $E_\mathrm{final} - E_\mathrm{initial}$.

§Example
use hoomd_interaction::{External, TotalEnergy, external::ConstantForce};
use hoomd_microstate::{Body, Microstate, property::Point};
use hoomd_vector::Cartesian;

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

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

let constant_force = External(ConstantForce {
    force: Cartesian::from([0.0, -1.0]),
    r_0: Cartesian::default(),
});

let delta_energy_total =
    constant_force.delta_energy_total(&microstate_a, &microstate_b);
assert_eq!(delta_energy_total, 1.0);
Source§

impl<E> StructuralPartialEq for External<E>

Auto Trait Implementations§

§

impl<E> Freeze for External<E>
where E: Freeze,

§

impl<E> RefUnwindSafe for External<E>
where E: RefUnwindSafe,

§

impl<E> Send for External<E>
where E: Send,

§

impl<E> Sync for External<E>
where E: Sync,

§

impl<E> Unpin for External<E>
where E: Unpin,

§

impl<E> UnsafeUnpin for External<E>
where E: UnsafeUnpin,

§

impl<E> UnwindSafe for External<E>
where E: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,