pub struct QuickCompress<C> { /* private fields */ }Expand description
Quickly compress a microstate to a target volume.
QuickCompress allows you to quickly compress a microstate to a
target volume. 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. It 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, QuickCompress is more than just a trial move, it
stores internal state to track its progress. Therefore, you should only use
a given QuickCompress on one Microstate.
When not complete, apply takes the following steps:
- Check the total energy of the given Hamiltonian.
- If the total energy is less than or equal to zero and the microstate
boundary’s volume does not match
target_volume, compress (or expand) the boundary a small amount toward the target. Reject any trial move that increases the per-site energy of the system more thanmaximum_energy_per_site. Accept in all other cases.
When the target volume is reached and the total energy is less than
or equal to 0, QuickCompress transitions to the complete state.
When complete, is_complete returns true and apply returns
immediately.
The generic type names are:
C: Theboundarycondition type.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);Implementations§
Source§impl<C> QuickCompress<C>
impl<C> QuickCompress<C>
Sourcepub fn with_target_volume(target_volume: PositiveReal) -> Self
pub fn with_target_volume(target_volume: PositiveReal) -> Self
Construct a new QuickCompress with the given target volume.
The returned QuickCompress will compress (or expand) the
microstate until the boundary reaches target_volume.
maximum_energy_per_sitedefaults to25.0.maximum_deltadefaults to0.01.
These defaults are suitable for use with the default
OverlapPenalty parameters applied to typical hard-particle
systems.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Check if the compression has completed.
is_complete will return true when the microstate has reached the
target volume and the total energy of the system was less than or
equal to zero during a call to apply. After that, is_complete
will continue to return true even when the system energy changes.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
assert!(!quick_compress.is_complete());Sourcepub fn target_volume(&self) -> PositiveReal
pub fn target_volume(&self) -> PositiveReal
Get the target volume
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
let target_volume = quick_compress.target_volume();
assert_eq!(target_volume.get(), 1000.0);Sourcepub fn set_target_volume(&mut self, target_volume: PositiveReal)where
C: Clone,
pub fn set_target_volume(&mut self, target_volume: PositiveReal)where
C: Clone,
Set the target volume.
Setting a new value will transition a complete QuickCompress to
an active state.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let mut quick_compress =
QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
quick_compress.set_target_volume(500.0.try_into()?);Sourcepub fn maximum_energy_per_site(&self) -> f64
pub fn maximum_energy_per_site(&self) -> f64
Get the maximum energy per site.
The largest energy per site allowed during apply.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
let maximum_energy_per_site = quick_compress.maximum_energy_per_site();Sourcepub fn maximum_energy_per_site_mut(&mut self) -> &mut f64
pub fn maximum_energy_per_site_mut(&mut self) -> &mut f64
A mutable reference to the maximum energy per site.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let mut quick_compress =
QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
*quick_compress.maximum_energy_per_site_mut() = 10.0;Sourcepub fn maximum_delta(&self) -> OpenUnitIntervalNumber
pub fn maximum_delta(&self) -> OpenUnitIntervalNumber
Get the maximum value of delta.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let quick_compress = QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
let maximum_delta = quick_compress.maximum_delta();Sourcepub fn maximum_delta_mut(&mut self) -> &mut OpenUnitIntervalNumber
pub fn maximum_delta_mut(&mut self) -> &mut OpenUnitIntervalNumber
A mutable reference to the maximum value of delta.
§Example
use hoomd_geometry::shape::Rectangle;
use hoomd_mc::QuickCompress;
use hoomd_microstate::boundary::Closed;
let mut quick_compress =
QuickCompress::<Closed<Rectangle>>::with_target_volume(
1000.0.try_into()?,
);
*quick_compress.maximum_delta_mut() = 0.001.try_into()?;Sourcepub fn apply<P, B, S, X, H, F>(
&mut self,
microstate: &mut Microstate<B, S, X, C>,
hamiltonian: &H,
should_map_body: F,
)where
P: Copy,
B: Clone + Position<Position = P> + Transform<S>,
S: Clone + Position<Position = P> + Default,
X: Clone + PointUpdate<P, SiteKey>,
H: TotalEnergy<Microstate<B, S, X, C>>,
C: Clone + MapPoint<P> + Wrap<B> + Wrap<S> + GenerateGhosts<S> + Volume + Scale + PartialEq,
Microstate<B, S, X, C>: Clone,
F: Fn(&Tagged<Body<B, S>>) -> bool,
pub fn apply<P, B, S, X, H, F>(
&mut self,
microstate: &mut Microstate<B, S, X, C>,
hamiltonian: &H,
should_map_body: F,
)where
P: Copy,
B: Clone + Position<Position = P> + Transform<S>,
S: Clone + Position<Position = P> + Default,
X: Clone + PointUpdate<P, SiteKey>,
H: TotalEnergy<Microstate<B, S, X, C>>,
C: Clone + MapPoint<P> + Wrap<B> + Wrap<S> + GenerateGhosts<S> + Volume + Scale + PartialEq,
Microstate<B, S, X, C>: Clone,
F: Fn(&Tagged<Body<B, S>>) -> bool,
Apply the quick compress algorithm to a microstate.
When the total energy of the microstate (given by hamiltonian) is less
than or equal to 0, apply scales the microstate’s boundary toward
the target_volume by an amount $1 \pm \delta$ where $\delta$
is a randomly sampled value between 0 and maximum_delta.
should_map_body controls how bodies in the microstate are transformed.
When should_map_body returns true, the body’s position will be mapped
from the initial boundary to the final (via MapPoint). When
should_map_body returns false, the body position is wrapped
into the boundary (via Wrap).
apply then evaluates the total energy change between the initial
and compressed microstates. To avoid introducing too much stress
into the system, it rejects moves where the total change in energy
per site is greater than maximum_energy_per_site.
Combine apply with local trial moves that translate and/or rotate
bodies by small amounts to relieve the stress caused by inserting
overlapping sites. Without local moves, the quick compress algorithm
will not achieve the target volume.
§Example
Hard spheres
use anyhow::anyhow;
use hoomd_geometry::{Volume, shape::Rectangle};
use hoomd_interaction::{
PairwiseCutoff,
pairwise::Isotropic,
univariate::{Expanded, OverlapPenalty},
};
use hoomd_mc::{QuickCompress, Sweep, Translate, Trial};
use hoomd_microstate::{
Body, Microstate, boundary::Periodic, property::Point,
};
use hoomd_simulation::macrostate::Isothermal;
use hoomd_vector::Cartesian;
let rectangle = Rectangle::with_equal_edges(16.0.try_into()?);
let mut quick_compress = QuickCompress::with_target_volume(200.0.try_into()?);
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)?)
.try_build()?;
for j in 0..8 {
let y = -8.0 + j as f64 * 2.0;
for i in 0..8 {
let x = -8.0 + i as f64 * 2.0;
microstate.add_body(Body::point(Cartesian::from([x, y])))?;
}
}
while(!quick_compress.is_complete()) {
quick_compress.apply(&mut microstate, &pairwise_cutoff, |_| true);
translate_sweep.apply(&mut microstate, &pairwise_cutoff, ¯ostate);
microstate.increment_step();
if microstate.step() > 10_000 {
let current = microstate.boundary().volume();
let target = quick_compress.target_volume();
let step = microstate.step();
return Err(anyhow!(
"Achieved volume {current} after {step} steps. The target was {target}."
));
}
}Trait Implementations§
Source§impl<C: Clone> Clone for QuickCompress<C>
impl<C: Clone> Clone for QuickCompress<C>
Source§fn clone(&self) -> QuickCompress<C>
fn clone(&self) -> QuickCompress<C>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<C: Debug> Debug for QuickCompress<C>
impl<C: Debug> Debug for QuickCompress<C>
Source§impl<'de, C> Deserialize<'de> for QuickCompress<C>where
C: Deserialize<'de>,
impl<'de, C> Deserialize<'de> for QuickCompress<C>where
C: Deserialize<'de>,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<C: PartialEq> PartialEq for QuickCompress<C>
impl<C: PartialEq> PartialEq for QuickCompress<C>
Source§impl<C> Serialize for QuickCompress<C>where
C: Serialize,
impl<C> Serialize for QuickCompress<C>where
C: Serialize,
impl<C> StructuralPartialEq for QuickCompress<C>
Auto Trait Implementations§
impl<C> Freeze for QuickCompress<C>where
C: Freeze,
impl<C> RefUnwindSafe for QuickCompress<C>where
C: RefUnwindSafe,
impl<C> Send for QuickCompress<C>where
C: Send,
impl<C> Sync for QuickCompress<C>where
C: Sync,
impl<C> Unpin for QuickCompress<C>where
C: Unpin,
impl<C> UnwindSafe for QuickCompress<C>where
C: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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