ising 0.2.3

Ising simulation and algorithms
Documentation
mod metropolis;
mod wolff;

pub use metropolis::Metropolis;
use rand::rngs::SmallRng;
pub use wolff::Wolff;

use crate::lattice::Lattice;

/// Algorithm type for builtin algorithms.
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum AlgorithmType {
    Wolff,
    Metropolis,
}

impl AlgorithmType {
    /// Name of the algorithm.
    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Wolff => "Wolff",
            Self::Metropolis => "Metropolis",
        }
    }

    /// Initializes the algorithm of the type.
    #[must_use]
    pub fn new_algorithm(&self, lattice: &Lattice, temperature: f64) -> Box<dyn Algorithm> {
        match self {
            Self::Wolff => Box::new(Wolff::new(lattice, temperature)),
            Self::Metropolis => Box::new(Metropolis::new(temperature)),
        }
    }
}

impl From<u8> for AlgorithmType {
    /// Analogously to `AlgorithmType` as u8.
    fn from(val: u8) -> Self {
        if val == Self::Wolff as u8 {
            Self::Wolff
        } else {
            Self::Metropolis
        }
    }
}

/// Trait to implement an Ising algorithm.
///
/// # Example
/// An example of implementing an algorithm not builtin.
/// ```
/// use rand::{rngs::SmallRng, SeedableRng};
/// use ising::{lattice::{Lattice, Spin}, Simulation, algorithm::AlgorithmType, CRITICAL_TEMPERATURE};
/// use ising::algorithm::{Algorithm, Metropolis};
///
/// struct ExampleAlgorithm {
///     temperature: f64,
/// }
///
/// impl ExampleAlgorithm {
///     pub fn new(temperature: f64) -> Self {
///         Self {
///             temperature,
///         }
///     }
/// }
///
/// impl Algorithm for ExampleAlgorithm {
///     fn set_temperature(&mut self, val: f64) {
///         self.temperature = val;
///     }
///
///     fn step(&mut self, lattice: &mut Lattice, rng: &mut SmallRng) {
///         // Just for demonstration.
///         if self.temperature > 2.0 {
///             let spin = Spin {x: 0, y: 0};
///             let old_value = lattice.value(&spin);
///             lattice.set_value(&spin, !old_value);
///         }
///     }
/// }
///
/// let side_length = 8;
/// let mut rng = SmallRng::seed_from_u64(42);
/// let lattice = Lattice::new(side_length, &mut rng);
///
/// let temperature = CRITICAL_TEMPERATURE;
/// let algorithm: Box<dyn Algorithm> = Box::new(ExampleAlgorithm::new(temperature));
///
/// let mut sim = Simulation::new(rng, lattice, temperature, algorithm);
/// sim.step();
/// ```
pub trait Algorithm {
    /// To be called on temperature change.
    fn set_temperature(&mut self, val: f64);

    /// Applies an algorithm step.
    fn step(&mut self, lattice: &mut Lattice, rng: &mut SmallRng);
}