QuickInsert

Struct QuickInsert 

Source
pub struct QuickInsert<D> { /* private fields */ }
Expand description

Quickly add bodies to the microstate with random configurations.

QuickInsert allows you to quickly insert many bodies into the microstate. It does so by breaking detailed balance, so you should use it only during the initialization phase of your simulation where you prepare a microstate for later equilibration.

QuickInsert works best with the OverlapPenalty potential that allows sites to overlap a small amount and for trial moves to partially reduce that overlap.

As a algorithm, QuickInsert is more than just a trial move, it stores internal state to track its progress. Therefore, you should only use a given QuickInsert on one Microstate. After initialization, a QuickInsert knows the target number of bodies it should add a distribution that places those bodies in the simulation boundary. New QuickInsert instances start in the running state.

When you apply a running QuickInsert to a microstate, it:

  1. Checks the total energy of the given Hamiltonian.
  2. If the total energy is less than or equal to zero and there are still bodies to insert, generate a random body and attempt to insert it into the microstate. Reject any insertion that would result in an infinite energy. Accept in all other cases.
  3. Repeat step 2 until inserted bodies overlap with others allowed_overlaps times, the target number of bodies have been inserted, or a total of target attempts have been made during this call, whichever comes first.

When both target bodies have been inserted and the energy is 0, QuickInsert transitions to the complete state. When complete, is_complete returns true and apply returns immediately.

For spherical particles, QuickInsert combined with OverlapPenalty can achieve a packing fraction of 56% in 3D and 72% in 2D. You might achieve slightly higher densities if you are willing to run many steps, though QuickCompress is a better solution.

The generic type names are:

  • D: The body distribution.

§Example

use hoomd_geometry::shape::Rectangle;
use hoomd_mc::{QuickInsert, UniformIn};
use hoomd_microstate::property::Point;
use hoomd_vector::Cartesian;

let rectangle = Rectangle::with_equal_edges(10.0.try_into()?);

let distribution = UniformIn {
    boundary: rectangle,
    template_sites: vec![Point::<Cartesian<2>>::default()],
};
let mut quick_insert = QuickInsert::new(distribution, 256);

Implementations§

Source§

impl<D> QuickInsert<D>

Source

pub fn new(distribution: D, target: usize) -> Self

Build a new quick insert algorithm.

After construction, the QuickInsert starts in a running state. On successive calls to apply, it will attempt to insert target bodies into the microstate randomly sampled from the given distribution. The default number of allowed_overlaps is target/8.

§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::{QuickInsert, UniformIn};
use hoomd_microstate::property::Point;
use hoomd_vector::Cartesian;

let rectangle = Rectangle::with_equal_edges(10.0.try_into()?);

let distribution = UniformIn {
    boundary: rectangle,
    template_sites: vec![Point::<Cartesian<2>>::default()],
};
let quick_insert = QuickInsert::new(distribution, 256);
Source

pub fn is_complete(&self) -> bool

Check if the quick insert algorithm is complete.

QuickInsert completes after it has inserted all target bodies and the total energy of the system is less than or equal to 0. When using the recommended OverlapPenalty potential, this means that that there are no overlaps between any particles.

§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::{QuickInsert, UniformIn};
use hoomd_microstate::property::Point;
use hoomd_vector::Cartesian;

let rectangle = Rectangle::with_equal_edges(10.0.try_into()?);

let distribution = UniformIn {
    boundary: rectangle,
    template_sites: vec![Point::<Cartesian<2>>::default()],
};
let quick_insert = QuickInsert::new(distribution, 256);

let complete = quick_insert.is_complete();
assert!(!complete);
Source

pub fn target(&self) -> usize

The target number of bodies to insert.

§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::{QuickInsert, UniformIn};
use hoomd_microstate::property::Point;
use hoomd_vector::Cartesian;

let rectangle = Rectangle::with_equal_edges(10.0.try_into()?);

let distribution = UniformIn {
    boundary: rectangle,
    template_sites: vec![Point::<Cartesian<2>>::default()],
};
let quick_insert = QuickInsert::new(distribution, 256);

let target = quick_insert.target();
assert_eq!(target, 256);
Source

pub fn apply<P, B, S, X, C, H>( &mut self, microstate: &mut Microstate<B, S, X, C>, hamiltonian: &H, ) -> Count
where P: Copy, B: Position<Position = P> + Transform<S>, S: Position<Position = P> + Default, X: PointUpdate<P, SiteKey>, D: BodyDistribution<Body<B, S>>, H: DeltaEnergyInsert<B, S, X, C> + TotalEnergy<Microstate<B, S, X, C>>, C: Wrap<B> + Wrap<S> + GenerateGhosts<S>,

Apply the quick insert algorithm to a microstate.

Combine QuickInsert::apply with local trial moves that translate and/or rotate bodies by small amounts to relieve the stress caused by inserting overlapping sites.

§Example

Hard spheres

use hoomd_geometry::shape::Rectangle;
use hoomd_interaction::{
    PairwiseCutoff,
    pairwise::Isotropic,
    univariate::{Expanded, OverlapPenalty},
};
use hoomd_mc::{QuickInsert, Sweep, Translate, Trial, UniformIn};
use hoomd_microstate::{
    Body, Microstate, boundary::Periodic, property::Point,
};
use hoomd_simulation::macrostate::Isothermal;
use hoomd_vector::Cartesian;

let rectangle = Rectangle::with_equal_edges(10.0.try_into()?);

let distribution = UniformIn {
    boundary: rectangle.clone(),
    template_sites: vec![Point::default()],
};
let mut quick_insert = QuickInsert::new(distribution, 256);

let translate = Translate::with_maximum_distance(0.1.try_into()?);
let mut translate_sweep = Sweep(translate);

let pairwise_cutoff = PairwiseCutoff(Isotropic {
    interaction: Expanded {
        delta: 1.0,
        f: OverlapPenalty::default(),
    },
    r_cut: 1.0,
});

let macrostate = Isothermal { temperature: 1.0 };
let mut microstate = Microstate::builder()
    .boundary(Periodic::new(1.0, rectangle)?)
    .bodies([Body::point(Cartesian::from([0.0, 0.0]))])
    .try_build()?;

quick_insert.apply(&mut microstate, &pairwise_cutoff);

translate_sweep.apply(&mut microstate, &pairwise_cutoff, &macrostate);

assert!(microstate.bodies().len() > 1);

Trait Implementations§

Source§

impl<D: Clone> Clone for QuickInsert<D>

Source§

fn clone(&self) -> QuickInsert<D>

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<D: Debug> Debug for QuickInsert<D>

Source§

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

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

impl<'de, D> Deserialize<'de> for QuickInsert<D>
where D: 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<D: PartialEq> PartialEq for QuickInsert<D>

Source§

fn eq(&self, other: &QuickInsert<D>) -> 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<D> Serialize for QuickInsert<D>
where D: 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<D> StructuralPartialEq for QuickInsert<D>

Auto Trait Implementations§

§

impl<D> Freeze for QuickInsert<D>
where D: Freeze,

§

impl<D> RefUnwindSafe for QuickInsert<D>
where D: RefUnwindSafe,

§

impl<D> Send for QuickInsert<D>
where D: Send,

§

impl<D> Sync for QuickInsert<D>
where D: Sync,

§

impl<D> Unpin for QuickInsert<D>
where D: Unpin,

§

impl<D> UnwindSafe for QuickInsert<D>
where D: 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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,