diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f0c46c03..071c8a99 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,21 @@ version: 2 updates: + +# main crate - package-ecosystem: cargo directory: "/" schedule: interval: daily open-pull-requests-limit: 10 target-branch: develop + +# procedural macro +- package-ecosystem: cargo + directory: "/procedural_macro/" + schedule: + interval: daily + open-pull-requests-limit: 10 + target-branch: develop + label: + - "dependencies" + - "macro" diff --git a/.gitignore b/.gitignore index 4f44c81f..e10c054a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ Cargo.lock **/*.rs.bk data/ .vscode/settings.json +logo.png diff --git a/CHANGELOG.md b/CHANGELOG.md index a304994f..dc4214f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,14 @@ First release - thread::ThreadError::Panic now contain a vector of error - fixe issue with the threading module's function giving inconsistent error type -- iterator opac type returned now also implement ExactSizeIterator and FusedIterator -- add licences MIT or APACHE-2.0 +- iterator opaque type returned now also implement ExactSizeIterator and FusedIterator +- add licenses MIT or APACHE-2.0 - add documentation - correct doctest Su3Adjoint::as_mut_vector - migrate to rust 2021 -- use readme in librairies root documentation -- rename lots of gettet to match C-GETTER convention -- rename some structure for C-WORD-ORDER \ No newline at end of file +- use readme in libraries root documentation +- rename lots of getter to match C-GETTER convention +- rename some structure for C-WORD-ORDER +- Rename `LatticeCylcique` to `LatticeCyclic` +- Rename `SimulationStateSynchrone` to `SimulationStateSynchronous` +- Rename structures and functions to correct spelling mistakes \ No newline at end of file diff --git a/README.md b/README.md index 09a2f765..9cc24a69 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ use lq::prelude::*; let beta = 1_f64; let mut simulation = - LatticeStateDefault::<4>::new_deterministe(size, beta, number_of_pts, &mut rng)?; + LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?; let spread_parameter = 0.1_f64; let mut mc = MetropolisHastingsDeltaDiagnostic::new(spread_parameter, rng)?; @@ -74,7 +74,7 @@ use lq::prelude::*; simulation.normalize_link_matrices(); } - let average = simulation.average_trace_plaquette().unwrap().real() / 3_f64; + let average = simulation.average_trace_plaquette().ok_or(ImplementationError::Unreachable)?.real() / 3_f64; # Ok(()) # } ``` @@ -153,7 +153,7 @@ let size = 1_000_f64; let number_of_pts = 4; let beta = 2_f64; let mut simulation = - LatticeStateDefault::<4>::new_deterministe(size, beta, number_of_pts, &mut rng)?; + LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?; let spread_parameter = 1E-5_f64; let mut mc = MetropolisHastingsDeltaDiagnostic::new(spread_parameter, rng) @@ -188,7 +188,7 @@ let size = 1_000_f64; let number_of_pts = 4; let beta = 2_f64; let mut simulation = - LatticeStateDefault::<3>::new_deterministe(size, beta, number_of_pts, &mut rng)?; + LatticeStateDefault::<3>::new_determinist(size, beta, number_of_pts, &mut rng)?; let number_of_rand = 20; let spread_parameter = 1E-5_f64; @@ -219,7 +219,7 @@ let size = 1_000_f64; let number_of_pts = 4; let beta = 2_f64; let mut simulation = - LatticeStateDefault::<3>::new_deterministe(size, beta, number_of_pts, &mut rng)?; + LatticeStateDefault::<3>::new_determinist(size, beta, number_of_pts, &mut rng)?; let delta_t = 1E-3_f64; let number_of_step = 10; diff --git a/benches/bench.rs b/benches/bench.rs index e4246b07..fd623f52 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -8,12 +8,12 @@ use lattice_qcd_rs::{ }; use rayon::prelude::*; -fn bench_simulation_creation_deterministe( +fn bench_simulation_creation_determinist( size: usize, rng: &mut rand::rngs::ThreadRng, d: &impl rand_distr::Distribution, ) { - let _simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let _simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 1_f64, 1_f64, size, rng, d, ) .unwrap(); @@ -103,18 +103,18 @@ fn criterion_benchmark(c: &mut Criterion) { let mut rng = rand::thread_rng(); let d = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let mut groupe_creation_deterministe = c.benchmark_group("Sim creation deterministe"); - groupe_creation_deterministe.sample_size(10); + let mut groupe_creation_determinist = c.benchmark_group("Sim creation determinist"); + groupe_creation_determinist.sample_size(10); let array_size: [usize; 6] = [2, 4, 8, 10, 20, 30]; for el in array_size.iter() { - groupe_creation_deterministe.throughput(Throughput::Elements((el.pow(4)) as u64)); - groupe_creation_deterministe.bench_with_input( + groupe_creation_determinist.throughput(Throughput::Elements((el.pow(4)) as u64)); + groupe_creation_determinist.bench_with_input( BenchmarkId::new("size", el.pow(4)), el, - |b, i| b.iter(|| bench_simulation_creation_deterministe(*i, &mut rng, &d)), + |b, i| b.iter(|| bench_simulation_creation_determinist(*i, &mut rng, &d)), ); } - groupe_creation_deterministe.finish(); + groupe_creation_determinist.finish(); let mut groupe_creation_threaded = c.benchmark_group("Sim creation (20) threaded"); let gp_size: usize = 20; @@ -170,7 +170,7 @@ fn criterion_benchmark(c: &mut Criterion) { groupe_mc.bench_function("simulate 20 D3 Metropolis Hastings Sweep", |b| { b.iter_batched( - || LatticeStateDefault::<3>::new_deterministe(1000_f64, 2_f64, 20, &mut rng).unwrap(), + || LatticeStateDefault::<3>::new_determinist(1000_f64, 2_f64, 20, &mut rng).unwrap(), |state_in| state_in.monte_carlo_step(&mut mc), BatchSize::LargeInput, ) @@ -181,7 +181,7 @@ fn criterion_benchmark(c: &mut Criterion) { groupe_mc.bench_function("simulate 20 D3 hybrid monteCarlo 100", |b| { b.iter_batched( - || LatticeStateDefault::<3>::new_deterministe(1000_f64, 2_f64, 20, &mut rng).unwrap(), + || LatticeStateDefault::<3>::new_determinist(1000_f64, 2_f64, 20, &mut rng).unwrap(), |state_in| state_in.monte_carlo_step(&mut mch), BatchSize::LargeInput, ) @@ -196,9 +196,9 @@ fn criterion_benchmark(c: &mut Criterion) { groupe_gauss_proj.bench_with_input(BenchmarkId::new("size", n), n, |b, i| { b.iter(|| { let state = - LatticeStateDefault::<4>::new_deterministe(1_f64, 1_f64, *i, &mut rng).unwrap(); + LatticeStateDefault::<4>::new_determinist(1_f64, 1_f64, *i, &mut rng).unwrap(); let d = rand_distr::Normal::new(0.0, 0.5_f64).unwrap(); - let e_field = EField::new_deterministe(state.lattice(), &mut rng, &d); + let e_field = EField::new_determinist(state.lattice(), &mut rng, &d); e_field.project_to_gauss(state.link_matrix(), state.lattice()); }) }); diff --git a/procedural_macro/Cargo.toml b/procedural_macro/Cargo.toml index 026de46b..8c4925da 100644 --- a/procedural_macro/Cargo.toml +++ b/procedural_macro/Cargo.toml @@ -12,8 +12,8 @@ publish = true proc-macro = true [dependencies] -quote = "1.0.16" -syn = "1.0.89" +quote = "1.0.17" +syn = "1.0.90" proc-macro2 = "1.0.36" [dev-dependencies] diff --git a/procedural_macro/src/lib.rs b/procedural_macro/src/lib.rs index 0d5825cb..bb823373 100644 --- a/procedural_macro/src/lib.rs +++ b/procedural_macro/src/lib.rs @@ -38,13 +38,13 @@ mod test; use proc_macro::TokenStream; use quote::quote; -/// Maximum dimention to impl [`Direction`] for. +/// Maximum dimension to impl [`Direction`] for. const MAX_DIM: usize = 127; /// Implement [`DirectionList`](https://abouttefeux.github.io/lattice-qcd-rs/lattice_qcd_rs/lattice/trait.DirectionList.html) /// for [`Direction`](https://abouttefeux.github.io/lattice-qcd-rs/lattice_qcd_rs/lattice/struct.Direction.html) of `1` to `127` the value of `MAX_DIM`. /// -/// Using const generics might render this unecessary. Waiting for stabilisation of feature(generic_const_exprs). +/// Using const generics might render this unnecessary. Waiting for stabilization of feature(generic_const_exprs). #[proc_macro] pub fn implement_direction_list(_item: TokenStream) -> TokenStream { let mut implem = Vec::with_capacity(MAX_DIM); @@ -66,7 +66,7 @@ pub fn implement_direction_list(_item: TokenStream) -> TokenStream { let u_dir_ident = syn::Ident::new(&format!("U{}_DIR", i), proc_macro2::Span::call_site()); let u_dir_pos_ident = syn::Ident::new(&format!("U{}_DIR_POS", i), proc_macro2::Span::call_site()); - // we store the vallues in array so we can access them as fast as possible. + // we store the values in array so we can access them as fast as possible. let s = quote! { const #u_dir_ident: [Direction<#i>; #i * 2] = [ #(#array_direction),* ]; const #u_dir_pos_ident: [Direction<#i>; #i] = [ #(#array_direction_positives),* ]; @@ -90,7 +90,7 @@ pub fn implement_direction_list(_item: TokenStream) -> TokenStream { final_stream.into() } -/// The max dimention to imply the [`From`] and [`std::convert::TryFrom`] and for +/// The max dimension to imply the [`From`] and [`std::convert::TryFrom`] and for /// [`Direction`](https://abouttefeux.github.io/lattice-qcd-rs/lattice_qcd_rs/lattice/struct.Direction.html). /// /// It takes just way to long for 127. @@ -108,14 +108,14 @@ pub fn implement_direction_from(_item: TokenStream) -> TokenStream { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[non_exhaustive] pub enum DirectionConversionError { - /// The index is out of bound, i.e. the directtion axis does not exist in the lower space dimention. + /// The index is out of bound, i.e. the direction axis does not exist in the lower space dimension. IndexOutOfBound, } impl std::fmt::Display for DirectionConversionError{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::IndexOutOfBound => write!(f, "the index is out of bound, the direction axis does not exist in the lower space dimention"), + Self::IndexOutOfBound => write!(f, "the index is out of bound, the direction axis does not exist in the lower space dimension"), } } } diff --git a/src/dim.rs b/src/dim.rs index 5acb3351..fd04c511 100644 --- a/src/dim.rs +++ b/src/dim.rs @@ -1,7 +1,7 @@ //! Depreciated, module for dimension reexport. //! -//! The library use now const generic and not this sytem anymore. It can be safely ignored. -//! It a sytem used before const generic was introduced. +//! The library use now const generic and not this system anymore. It can be safely ignored. +//! It a was system used before const generic was introduced. macro_rules! reexport_name_dim{ ($($i:ident) ,+) => { diff --git a/src/error.rs b/src/error.rs index 8b2c1895..8f457538 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,7 @@ //! Defines different error types. +// TODO unwrap, panic and expect => error make a issue on git + use std::error::Error; use std::fmt::{self, Debug, Display, Formatter}; @@ -8,8 +10,38 @@ use serde::{Deserialize, Serialize}; use crate::thread::ThreadError; -/// A type that can never be (safly) initialized. -/// This is temporary, until [`never`](https://doc.rust-lang.org/std/primitive.never.html) is accepted into stable rust. +/// A type that can never be (safely) initialized. +/// This is temporary, until [`never`](https://doc.rust-lang.org/std/primitive.never.html) +/// is accepted into stable rust. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::error::Never; +/// trait Something { +/// type Error; +/// +/// fn do_something(&self) -> Result<(), Self::Error>; +/// } +/// +/// struct SomethingImpl; +/// +/// impl Something for SomethingImpl { +/// type Error = Never; // We never have an error +/// +/// fn do_something(&self) -> Result<(), Self::Error> { +/// // implementation that never fails +/// Ok(()) +/// } +/// } +/// ``` +/// the size of [`Never`] is 0 +/// ``` +/// # use lattice_qcd_rs::error::Never; +/// assert_eq!(std::mem::size_of::(), 0); +/// // the size is still zero. because () is size 0. +/// assert_eq!(std::mem::size_of::>(), 0); +/// assert_eq!(std::mem::size_of::>(), 1); +/// ``` #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum Never {} @@ -24,15 +56,16 @@ impl Error for Never {} /// Errors in the implementation of the library. This is unwanted to return this type but /// sometimes this is better to return that instead of panicking. It is also used in some example. +// TODO example #[non_exhaustive] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum ImplementationError { - /// We atain a portion of the code that was tought to be unreachable. + /// We attain a portion of the code that was thought to be unreachable. Unreachable, /// An option contained an unexpected None value. /// - /// Used when needing to retrun a dyn Error but `std::option::NoneError` does not implement [`Error`] + /// Used when needing to return a dyn Error but `std::option::NoneError` does not implement [`Error`] // TODO NoneError OptionWithUnexpectedNone, } @@ -53,13 +86,14 @@ impl Display for ImplementationError { impl Error for ImplementationError {} /// Error return while doing multiple steps. +// TODO example #[non_exhaustive] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum MultiIntegrationError { - /// atempting to integrate doing zero steps + /// attempting to integrate doing zero steps ZeroIntegration, - /// An intgration error occured at the position of the first field. + /// An integration error occurred at the position of the first field. IntegrationError(usize, Error), } @@ -68,7 +102,7 @@ impl Display for MultiIntegrationError { match self { MultiIntegrationError::ZeroIntegration => write!(f, "no integration steps"), MultiIntegrationError::IntegrationError(index, error) => { - write!(f, "error during intgration step {}: {}", index, error) + write!(f, "error during integration step {}: {}", index, error) } } } @@ -83,13 +117,14 @@ impl Error for MultiIntegrationError { } } -/// Error while initialising a state +/// Error while initializing a state +// TODO example #[non_exhaustive] #[derive(Clone, Debug, PartialEq, Copy, Eq)] pub enum StateInitializationError { /// The parameter given for the normal distribution is incorrect. - InvalideParameterNormalDistribution(rand_distr::NormalError), - /// Size of lattice and data are imcompatible + InvalidParameterNormalDistribution(rand_distr::NormalError), + /// Size of lattice and data are incompatible IncompatibleSize, /// [`LatticeInitializationError`] LatticeInitializationError(LatticeInitializationError), @@ -97,7 +132,7 @@ pub enum StateInitializationError { impl From for StateInitializationError { fn from(err: rand_distr::NormalError) -> Self { - Self::InvalideParameterNormalDistribution(err) + Self::InvalidParameterNormalDistribution(err) } } @@ -110,10 +145,10 @@ impl From for StateInitializationError { impl Display for StateInitializationError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Self::InvalideParameterNormalDistribution(error) => { + Self::InvalidParameterNormalDistribution(error) => { write!(f, "normal distribution error: {}", error) } - Self::IncompatibleSize => write!(f, "size of lattice and data are imcompatible"), + Self::IncompatibleSize => write!(f, "size of lattice and data are incompatible"), Self::LatticeInitializationError(err) => { write!(f, "lattice Initialization error: {}", err) } @@ -124,14 +159,15 @@ impl Display for StateInitializationError { impl Error for StateInitializationError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { - Self::InvalideParameterNormalDistribution(error) => Some(error), + Self::InvalidParameterNormalDistribution(error) => Some(error), Self::IncompatibleSize => None, Self::LatticeInitializationError(err) => Some(err), } } } -/// Error while initialising a state using multiple thread or threded function. +/// Error while initializing a state using multiple thread or threaded function. +// TODO example #[non_exhaustive] #[derive(Debug, Clone, Eq, PartialEq)] pub enum ThreadedStateInitializationError { @@ -171,16 +207,17 @@ impl Error for ThreadedStateInitializationError { } } -/// Error while initialising a lattice +/// Error while initializing a lattice +// TODO example #[non_exhaustive] #[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum LatticeInitializationError { - /// `size` must be stricly greater 0 than and be a finite number. + /// `size` must be strictly greater 0 than and be a finite number. NonPositiveSize, /// `dim` must be greater than 2. DimTooSmall, - /// the dimension parameter `D = 0` is not valide. + /// the dimension parameter `D = 0` is not valid. ZeroDimension, } @@ -189,7 +226,7 @@ impl Display for LatticeInitializationError { match self { Self::NonPositiveSize => write!( f, - "`size` must be stricly greater than 0 and be a finite number" + "`size` must be strictly greater than 0 and be a finite number" ), Self::DimTooSmall => write!(f, "`dim` must be greater or equal to 2"), Self::ZeroDimension => write!(f, "the dimension parameter `D = 0` is not valid"), @@ -200,21 +237,22 @@ impl Display for LatticeInitializationError { impl Error for LatticeInitializationError {} /// A struct that combine an error with a owned value +// TODO example / remove #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -pub struct ErrorWithOnwnedValue { +pub struct ErrorWithOwnedValue { error: Error, owned: State, } -impl ErrorWithOnwnedValue { +impl ErrorWithOwnedValue { getter!( - /// getter on the error + /// Getter on the error. pub const error() -> Error ); getter!( - /// getter on the owned value + /// Getter on the owned value. pub const owned() -> State ); @@ -223,51 +261,51 @@ impl ErrorWithOnwnedValue { Self { error, owned } } - /// Deconstruct the structur. + /// Deconstruct the structure. #[allow(clippy::missing_const_for_fn)] // false positive pub fn deconstruct(self) -> (Error, State) { (self.error, self.owned) } - /// Deconstruct the structur returning the error and discarding the owned value. + /// Deconstruct the structure returning the error and discarding the owned value. #[allow(clippy::missing_const_for_fn)] // false positive pub fn error_owned(self) -> Error { self.error } } -impl From<(Error, State)> for ErrorWithOnwnedValue { +impl From<(Error, State)> for ErrorWithOwnedValue { fn from(data: (Error, State)) -> Self { Self::new(data.0, data.1) } } -impl Display for ErrorWithOnwnedValue { +impl Display for ErrorWithOwnedValue { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "error {} with data {}", self.error, self.owned) } } impl Error - for ErrorWithOnwnedValue + for ErrorWithOwnedValue { fn source(&self) -> Option<&(dyn Error + 'static)> { Some(&self.error) } } -impl From> +impl From> for StateInitializationError { - fn from(data: ErrorWithOnwnedValue) -> Self { + fn from(data: ErrorWithOwnedValue) -> Self { data.error } } -impl From> - for ErrorWithOnwnedValue +impl From> + for ErrorWithOwnedValue { - fn from(data: ErrorWithOnwnedValue) -> Self { + fn from(data: ErrorWithOwnedValue) -> Self { Self::new(data.error, data.owned.0) } } @@ -300,9 +338,15 @@ mod test { let e2 = MultiIntegrationError::IntegrationError(index, error); assert_eq!( e2.to_string(), - format!("error during intgration step {}: {}", index, error) + format!("error during integration step {}: {}", index, error) ); assert!(e1.source().is_none()); assert!(e2.source().is_some()); } + + #[allow(clippy::missing_const_for_fn)] // cannot test const function + #[test] + fn never_size() { + assert_eq!(std::mem::size_of::(), 0); + } } diff --git a/src/field.rs b/src/field.rs index b956fc0b..1fc2fa0e 100644 --- a/src/field.rs +++ b/src/field.rs @@ -13,10 +13,10 @@ use rayon::prelude::*; use serde::{Deserialize, Serialize}; use super::{ - lattice::{Direction, LatticeCyclique, LatticeElementToIndex, LatticeLink, LatticePoint}, + lattice::{Direction, LatticeCyclic, LatticeElementToIndex, LatticeLink, LatticePoint}, su3, su3::GENERATORS, - thread::{run_pool_parallel_vec_with_initialisation_mutable, ThreadError}, + thread::{run_pool_parallel_vec_with_initializations_mutable, ThreadError}, utils::levi_civita, CMatrix3, Complex, Real, Vector8, I, }; @@ -35,10 +35,10 @@ impl Su3Adjoint { /// create a new Su3Adjoint representation where `M = M^a T^a`, where `T` are generators given in [`su3::GENERATORS`]. /// # Example /// ``` - /// extern crate nalgebra; /// use lattice_qcd_rs::field::Su3Adjoint; + /// use nalgebra::SVector; /// - /// let su3 = Su3Adjoint::new(nalgebra::SVector::::from_element(1_f64)); + /// let su3 = Su3Adjoint::new(SVector::::from_element(1_f64)); /// ``` pub const fn new(data: Vector8) -> Self { Self { data } @@ -59,7 +59,8 @@ impl Su3Adjoint { &self.data } - /// get the su3 adjoint as a [`Vector8`] + /// Get the su3 adjoint as a [`Vector8`]. + /// /// # Example /// ``` /// # use lattice_qcd_rs::field::Su3Adjoint; @@ -72,7 +73,8 @@ impl Su3Adjoint { self.data() } - /// get the su3 adjoint as mut ref to a [`Vector8`] + /// Get the su3 adjoint as mut ref to a [`Vector8`]. + /// /// # Example /// ``` /// # use lattice_qcd_rs::{field::Su3Adjoint, Vector8}; @@ -92,17 +94,18 @@ impl Su3Adjoint { self.data_mut() } - /// return the su(3) (Lie algebra) matrix. + /// Returns the su(3) (Lie algebra) matrix. + /// /// # Example /// ``` /// # use lattice_qcd_rs::{field::Su3Adjoint}; /// let su3 = Su3Adjoint::new_from_array([1_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64]); /// assert_eq!(su3.to_matrix(), *lattice_qcd_rs::su3::GENERATORS[0]); /// ``` - // TODO self non consomé ?? passé en &self ? TODO bench + // TODO self non consumed ?? passé en &self ? TODO bench pub fn to_matrix(self) -> Matrix3> { self.data - .iter() + .into_iter() .enumerate() .map(|(pos, el)| *GENERATORS[pos] * na::Complex::::from(el)) .sum() @@ -110,9 +113,9 @@ impl Su3Adjoint { /// Return the SU(3) matrix associated with this generator. /// Note that the function consume self. + /// /// # Example /// ``` - /// # extern crate nalgebra; /// # use lattice_qcd_rs::{field::Su3Adjoint}; /// let su3 = Su3Adjoint::new_from_array([1_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64, 0_f64]); /// assert_eq!(su3.to_su3().determinant(), nalgebra::Complex::from(1_f64)); @@ -123,13 +126,14 @@ impl Su3Adjoint { su3::su3_exp_i(self) } - /// return exp( T^a v^a) where v is self. + /// Return exp( T^a v^a) where v is self. /// Note that the function consume self. pub fn exp(self) -> Matrix3> { su3::su3_exp_r(self) } - /// create a new random SU3 adjoint. + /// Create a new random SU3 adjoint. + /// /// # Example /// ``` /// use lattice_qcd_rs::field::Su3Adjoint; @@ -166,6 +170,7 @@ impl Su3Adjoint { /// If you are looking for the trace square use [Self::trace_squared] instead. /// /// It is used for [`su3::su3_exp_i`]. + /// /// # Example /// ``` /// # use lattice_qcd_rs::field::Su3Adjoint; @@ -182,7 +187,8 @@ impl Su3Adjoint { } /// Return the t coeff `d = i * det(X)`. - /// Used for [`su3::su3_exp_i`] + /// Used for [`su3::su3_exp_i`]. + /// /// # Example /// ``` /// # use lattice_qcd_rs::field::Su3Adjoint; @@ -204,11 +210,23 @@ impl Su3Adjoint { /// # let su3 = Su3Adjoint::new(nalgebra::SVector::::zeros()); /// assert_eq!(su3.len(), 8); /// ``` + #[allow(clippy::unused_self)] pub fn len(&self) -> usize { self.data.len() + //8 } - /// Get an iterator over the ellements. + /// Return the number of data. This number is 8 + /// ``` + /// # use lattice_qcd_rs::field::Su3Adjoint; + /// let su3 = Su3Adjoint::new(nalgebra::SVector::::zeros()); + /// assert_eq!(Su3Adjoint::len_const(), su3.len()); + /// ``` + pub const fn len_const() -> usize { + 8 + } + + /// Get an iterator over the elements. /// /// # Example /// ``` @@ -220,7 +238,8 @@ impl Su3Adjoint { self.data.iter() } - /// Get an iterator over the mutable ref of ellements. + /// Get an iterator over the mutable ref of elements. + /// /// # Example /// ``` /// # use lattice_qcd_rs::field::Su3Adjoint; @@ -233,7 +252,7 @@ impl Su3Adjoint { self.data.iter_mut() } - /// Get a mutlable reference over the data. + /// Get a mutable reference over the data. pub fn data_mut(&mut self) -> &mut Vector8 { &mut self.data } @@ -482,6 +501,7 @@ impl Neg for &Su3Adjoint { /// Return the representation for the zero matrix. impl Default for Su3Adjoint { /// Return the representation for the zero matrix. + /// /// # Example /// ``` /// # use lattice_qcd_rs::field::Su3Adjoint; @@ -504,7 +524,8 @@ impl std::fmt::Display for Su3Adjoint { impl Index for Su3Adjoint { type Output = Real; - /// Get the element at position `pos` + /// Get the element at position `pos`. + /// /// # Panic /// Panics if the position is out of bound (greater or equal to 8). /// ```should_panic @@ -518,7 +539,8 @@ impl Index for Su3Adjoint { } impl IndexMut for Su3Adjoint { - /// Get the element at position `pos` + /// Get the element at position `pos`. + /// /// # Panic /// Panics if the position is out of bound (greater or equal to 8). /// ```should_panic @@ -564,7 +586,7 @@ pub struct LinkMatrix { } impl LinkMatrix { - /// Creat a new link matrix field from preexisting data. + /// Create a new link matrix field from preexisting data. pub const fn new(data: Vec>>) -> Self { Self { data } } @@ -602,9 +624,10 @@ impl LinkMatrix { /// Single threaded generation with a given random number generator. /// useful to produce a deterministic set of data but slower than /// [`LinkMatrix::new_random_threaded`]. + /// /// # Example /// ``` - /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclique}; + /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclic}; /// use rand::{rngs::StdRng, SeedableRng}; /// # use std::error::Error; /// @@ -612,20 +635,20 @@ impl LinkMatrix { /// let mut rng_1 = StdRng::seed_from_u64(0); /// let mut rng_2 = StdRng::seed_from_u64(0); /// // They have the same seed and should generate the same numbers - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4)?; + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; /// assert_eq!( - /// LinkMatrix::new_deterministe(&lattice, &mut rng_1), - /// LinkMatrix::new_deterministe(&lattice, &mut rng_2) + /// LinkMatrix::new_determinist(&lattice, &mut rng_1), + /// LinkMatrix::new_determinist(&lattice, &mut rng_2) /// ); /// # Ok(()) /// # } /// ``` - pub fn new_deterministe( - l: &LatticeCyclique, + pub fn new_determinist( + l: &LatticeCyclic, rng: &mut Rng, ) -> Self { // l.get_links_space().map(|_| Su3Adjoint::random(rng, d).to_su3()).collect() - // using a for loop imporves performance. ( probably because the vector is pre allocated). + // using a for loop improves performance. ( probably because the vector is pre allocated). let mut data = Vec::with_capacity(l.number_of_canonical_links_space()); for _ in l.get_links() { // the iterator *should* be in order @@ -641,11 +664,11 @@ impl LinkMatrix { /// /// # Example /// ``` - /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclique}; + /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclic}; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { - /// let lattice = LatticeCyclique::<3>::new(1_f64, 4)?; + /// let lattice = LatticeCyclic::<3>::new(1_f64, 4)?; /// let links = LinkMatrix::new_random_threaded(&lattice, 4)?; /// assert!(!links.is_empty()); /// # Ok(()) @@ -653,19 +676,19 @@ impl LinkMatrix { /// ``` /// /// # Errors - /// Returns [`ThreadError::ThreadNumberIncorect`] if `number_of_thread` is 0. + /// Returns [`ThreadError::ThreadNumberIncorrect`] if `number_of_thread` is 0. pub fn new_random_threaded( - l: &LatticeCyclique, + l: &LatticeCyclic, number_of_thread: usize, ) -> Result { if number_of_thread == 0 { - return Err(ThreadError::ThreadNumberIncorect); + return Err(ThreadError::ThreadNumberIncorrect); } else if number_of_thread == 1 { let mut rng = rand::thread_rng(); - return Ok(LinkMatrix::new_deterministe(l, &mut rng)); + return Ok(LinkMatrix::new_determinist(l, &mut rng)); } - let data = run_pool_parallel_vec_with_initialisation_mutable( + let data = run_pool_parallel_vec_with_initializations_mutable( l.get_links(), &(), &|rng, _, _| su3::random_su3(rng), @@ -678,20 +701,21 @@ impl LinkMatrix { Ok(Self { data }) } - /// Create a cold configuration ( where the link matrices is set to the indentity). + /// Create a cold configuration ( where the link matrices is set to the identity). + /// /// # Example /// ``` - /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclique}; + /// use lattice_qcd_rs::{field::LinkMatrix, lattice::LatticeCyclic}; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { - /// let lattice = LatticeCyclique::<3>::new(1_f64, 4)?; + /// let lattice = LatticeCyclic::<3>::new(1_f64, 4)?; /// let links = LinkMatrix::new_cold(&lattice); /// assert!(!links.is_empty()); /// # Ok(()) /// # } /// ``` - pub fn new_cold(l: &LatticeCyclique) -> Self { + pub fn new_cold(l: &LatticeCyclic) -> Self { Self { data: vec![CMatrix3::identity(); l.number_of_canonical_links_space()], } @@ -702,7 +726,7 @@ impl LinkMatrix { pub fn matrix( &self, link: &LatticeLink, - l: &LatticeCyclique, + l: &LatticeCyclic, ) -> Option>> { let link_c = l.into_canonical(*link); let matrix = self.data.get(link_c.to_index(l))?; @@ -721,7 +745,7 @@ impl LinkMatrix { point: &LatticePoint, dir_i: &Direction, dir_j: &Direction, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option>> { let u_j = self.matrix(&LatticeLink::new(*point, *dir_j), lattice)?; let point_pj = lattice.add_point_direction(*point, dir_j); @@ -739,7 +763,7 @@ impl LinkMatrix { point: &LatticePoint, dir_i: &Direction, dir_j: &Direction, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option>> { let s_ij = self.sij(point, dir_i, dir_j, lattice)?; let u_i = self.matrix(&LatticeLink::new(*point, *dir_i), lattice)?; @@ -750,7 +774,7 @@ impl LinkMatrix { #[allow(clippy::as_conversions)] // no try into for f64 pub fn average_trace_plaquette( &self, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option> { if lattice.number_of_canonical_links_space() != self.len() { return None; @@ -785,7 +809,7 @@ impl LinkMatrix { point: &LatticePoint, dir_i: &Direction, dir_j: &Direction, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { Some( self.pij(point, dir_i, dir_j, lattice)? @@ -795,26 +819,26 @@ impl LinkMatrix { ) } - /// Get the `F^{ij}` tensor using the clover appropriation. The direction should be set to positive - /// See arXive:1512.02374. + /// Get the `F^{ij}` tensor using the clover appropriation. The direction should be set to positive. + /// See . // TODO negative directions pub fn f_mu_nu( &self, point: &LatticePoint, dir_i: &Direction, dir_j: &Direction, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { let m = self.clover(point, dir_i, dir_j, lattice)? - self.clover(point, dir_j, dir_i, lattice)?; Some(m / Complex::from(8_f64 * lattice.size() * lattice.size())) } - /// Get the chromomagentic field at a given point + /// Get the chromomagnetic field at a given point. pub fn magnetic_field_vec( &self, point: &LatticePoint, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option> { let mut vec = SVector::::zeros(); for dir in &Direction::::positive_directions() { @@ -823,12 +847,12 @@ impl LinkMatrix { Some(vec) } - /// Get the chromomagentic field at a given point alongisde a given direction + /// Get the chromomagnetic field at a given point alongside a given direction. pub fn magnetic_field( &self, point: &LatticePoint, dir: &Direction, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { let sum = Direction::::positive_directions() .iter() @@ -848,11 +872,11 @@ impl LinkMatrix { Some(sum / Complex::new(0_f64, 2_f64)) } - /// Get the chromomagentic field at a given point alongisde a given direction given by lattice link + /// Get the chromomagnetic field at a given point alongside a given direction given by lattice link. pub fn magnetic_field_link( &self, link: &LatticeLink, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option>> { self.magnetic_field(link.pos(), link.dir(), lattice) } @@ -876,12 +900,12 @@ impl LinkMatrix { }); } - /// Iter on the data + /// Iter on the data. pub fn iter(&self) -> impl Iterator + ExactSizeIterator + FusedIterator { self.data.iter() } - /// Iter mutably on the data + /// Iter mutably on the data. pub fn iter_mut( &mut self, ) -> impl Iterator + ExactSizeIterator + FusedIterator { @@ -1018,17 +1042,17 @@ impl EField { &mut self.data } - /// Get the e_field as a Vec of Vector of Su3Adjoint + /// Get the e_field as a Vec of Vector of [`Su3Adjoint`] pub const fn as_vec(&self) -> &Vec> { self.data() } - /// Get the e_field as a slice of Vector of Su3Adjoint + /// Get the e_field as a slice of Vector of [`Su3Adjoint`] pub fn as_slice(&self) -> &[SVector] { &self.data } - /// Get the e_field as mut ref to slice of Vector of Su3Adjoint + /// Get the e_field as mut ref to slice of Vector of [`Su3Adjoint`] pub fn as_slice_mut(&mut self) -> &mut [SVector] { &mut self.data } @@ -1040,31 +1064,33 @@ impl EField { /// Single threaded generation with a given random number generator. /// useful to reproduce a set of data. + /// /// # Example /// ``` - /// extern crate rand; - /// extern crate rand_distr; - /// # use lattice_qcd_rs::{field::EField, lattice::LatticeCyclique}; + /// # use lattice_qcd_rs::{field::EField, lattice::LatticeCyclic}; + /// # fn main () -> Result<(), Box> { /// use rand::{rngs::StdRng, SeedableRng}; /// /// let mut rng_1 = StdRng::seed_from_u64(0); /// let mut rng_2 = StdRng::seed_from_u64(0); /// // They have the same seed and should generate the same numbers /// let distribution = rand::distributions::Uniform::from(-1_f64..1_f64); - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4).unwrap(); + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; /// assert_eq!( - /// EField::new_deterministe(&lattice, &mut rng_1, &distribution), - /// EField::new_deterministe(&lattice, &mut rng_2, &distribution) + /// EField::new_determinist(&lattice, &mut rng_1, &distribution), + /// EField::new_determinist(&lattice, &mut rng_2, &distribution) /// ); + /// # Ok(()) + /// # } /// ``` - pub fn new_deterministe( - l: &LatticeCyclique, + pub fn new_determinist( + l: &LatticeCyclic, rng: &mut Rng, d: &impl rand_distr::Distribution, ) -> Self { let mut data = Vec::with_capacity(l.number_of_points()); for _ in l.get_points() { - // iterator *should* be ordoned + // iterator *should* be ordered data.push(SVector::::from_fn(|_, _| { Su3Adjoint::random(rng, d) })); @@ -1073,40 +1099,41 @@ impl EField { } /// Single thread generation by seeding a new rng number. - /// To create a seedable and reproducible set use [`EField::new_deterministe`]. + /// To create a seedable and reproducible set use [`EField::new_determinist`]. /// /// # Example /// ``` - /// use lattice_qcd_rs::{field::EField, lattice::LatticeCyclique}; + /// use lattice_qcd_rs::{field::EField, lattice::LatticeCyclic}; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { /// let distribution = rand::distributions::Uniform::from(-1_f64..1_f64); - /// let lattice = LatticeCyclique::<3>::new(1_f64, 4)?; + /// let lattice = LatticeCyclic::<3>::new(1_f64, 4)?; /// let e_field = EField::new_random(&lattice, &distribution); /// assert!(!e_field.is_empty()); /// # Ok(()) /// # } /// ``` - pub fn new_random(l: &LatticeCyclique, d: &impl rand_distr::Distribution) -> Self { + pub fn new_random(l: &LatticeCyclic, d: &impl rand_distr::Distribution) -> Self { let mut rng = rand::thread_rng(); - EField::new_deterministe(l, &mut rng, d) + EField::new_determinist(l, &mut rng, d) } - /// Create a new cold configuration for the electriccal field, i.e. all E ar set to 0. + /// Create a new cold configuration for the electrical field, i.e. all E ar set to 0. + /// /// # Example /// ``` - /// use lattice_qcd_rs::{field::EField, lattice::LatticeCyclique}; + /// use lattice_qcd_rs::{field::EField, lattice::LatticeCyclic}; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { - /// let lattice = LatticeCyclique::<3>::new(1_f64, 4)?; + /// let lattice = LatticeCyclic::<3>::new(1_f64, 4)?; /// let e_field = EField::new_cold(&lattice); /// assert!(!e_field.is_empty()); /// # Ok(()) /// # } /// ``` - pub fn new_cold(l: &LatticeCyclique) -> Self { + pub fn new_cold(l: &LatticeCyclic) -> Self { let p1 = Su3Adjoint::new_from_array([0_f64; 8]); Self { data: vec![SVector::::from_element(p1); l.number_of_points()], @@ -1117,7 +1144,7 @@ impl EField { pub fn e_vec( &self, point: &LatticePoint, - l: &LatticeCyclique, + l: &LatticeCyclic, ) -> Option<&SVector> { self.data.get(point.to_index(l)) } @@ -1128,7 +1155,7 @@ impl EField { &self, point: &LatticePoint, dir: &Direction, - l: &LatticeCyclique, + l: &LatticeCyclic, ) -> Option<&Su3Adjoint> { let value = self.e_vec(point, l); match value { @@ -1148,7 +1175,7 @@ impl EField { &self, link_matrix: &LinkMatrix, point: &LatticePoint, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { if lattice.number_of_points() != self.len() || lattice.number_of_canonical_links_space() != link_matrix.len() @@ -1172,7 +1199,7 @@ impl EField { pub fn gauss_sum_div( &self, link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { if lattice.number_of_points() != self.len() || lattice.number_of_canonical_links_space() != link_matrix.len() @@ -1192,9 +1219,9 @@ impl EField { .sum::>() } - /// project to that the gauss law is approximatively respected ( up to `f64::EPSILON * 10` per point). + /// project to that the gauss law is approximately respected ( up to `f64::EPSILON * 10` per point). /// - /// It is mainly use internally but can be use to correct numerical drit in simulations. + /// It is mainly use internally but can be use to correct numerical drift in simulations. /// /// # Example /// ``` @@ -1202,7 +1229,7 @@ impl EField { /// use lattice_qcd_rs::integrator::SymplecticEulerRayon; /// use lattice_qcd_rs::simulation::{ /// LatticeState, LatticeStateDefault, LatticeStateEFSyncDefault, LatticeStateWithEField, - /// SimulationStateSynchrone, + /// SimulationStateSynchronous, /// }; /// use rand::SeedableRng; /// @@ -1213,16 +1240,16 @@ impl EField { /// let distribution = /// rand::distributions::Uniform::from(-std::f64::consts::PI..std::f64::consts::PI); /// let mut state = LatticeStateEFSyncDefault::new_random_e_state( - /// LatticeStateDefault::<3>::new_deterministe(1_f64, 6_f64, 4, &mut rng).unwrap(), + /// LatticeStateDefault::<3>::new_determinist(1_f64, 6_f64, 4, &mut rng)?, /// &mut rng, - /// ); // <- here internally when choosing radomly the EField it is projected. + /// ); // <- here internally when choosing randomly the EField it is projected. /// /// let integrator = SymplecticEulerRayon::default(); /// for _ in 0..2 { /// for _ in 0..10 { /// state = state.simulate_sync(&integrator, 0.0001_f64)?; /// } - /// // we correct the numberical drift of the EField. + /// // we correct the numerical drift of the EField. /// let new_e_field = state /// .e_field() /// .project_to_gauss(state.link_matrix(), state.lattice()) @@ -1238,7 +1265,7 @@ impl EField { pub fn project_to_gauss( &self, link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { // TODO improve const NUMBER_FOR_LOOP: usize = 4; @@ -1266,15 +1293,12 @@ impl EField { Some(return_val) } - /// Done one step to project to gauss law + /// Done one step to project to gauss law. + /// /// # Panic - /// panics if the link matric and lattice is not of the correct size. + /// panics if the link matrix and lattice is not of the correct size. #[inline] - fn project_to_gauss_step( - &self, - link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, - ) -> Self { + fn project_to_gauss_step(&self, link_matrix: &LinkMatrix, lattice: &LatticeCyclic) -> Self { /// see // TODO verify const K: na::Complex = na::Complex::new(0.12_f64, 0_f64); @@ -1434,7 +1458,7 @@ mod test { fn test_get_e_field_pos_neg() { use super::super::lattice; - let l = LatticeCyclique::new(1_f64, 4).unwrap(); + let l = LatticeCyclic::new(1_f64, 4).unwrap(); let e = EField::new(vec![SVector::<_, 4>::from([ Su3Adjoint::from([1_f64; 8]), Su3Adjoint::from([2_f64; 8]), @@ -1513,10 +1537,10 @@ mod test { #[test] fn link_matrix() { - let lattice = LatticeCyclique::<3>::new(1_f64, 4).unwrap(); + let lattice = LatticeCyclic::<3>::new(1_f64, 4).unwrap(); match LinkMatrix::new_random_threaded(&lattice, 0) { - Err(ThreadError::ThreadNumberIncorect) => {} - _ => panic!("unexpected ouptut"), + Err(ThreadError::ThreadNumberIncorrect) => {} + _ => panic!("unexpected output"), } let link_s = LinkMatrix::new_random_threaded(&lattice, 2); assert!(link_s.is_ok()); @@ -1537,7 +1561,7 @@ mod test { #[test] fn e_field() { - let lattice = LatticeCyclique::<3>::new(1_f64, 4).unwrap(); + let lattice = LatticeCyclic::<3>::new(1_f64, 4).unwrap(); let e_field_s = LinkMatrix::new_random_threaded(&lattice, 2); assert!(e_field_s.is_ok()); let mut e_field = e_field_s.unwrap(); @@ -1553,8 +1577,8 @@ mod test { } #[test] - fn mangetic_field() { - let lattice = LatticeCyclique::<3>::new(1_f64, 4).unwrap(); + fn magnetic_field() { + let lattice = LatticeCyclic::<3>::new(1_f64, 4).unwrap(); let mut link_matrix = LinkMatrix::new_cold(&lattice); let point = LatticePoint::from([0, 0, 0]); let dir_x = Direction::new(0, true).unwrap(); @@ -1685,4 +1709,10 @@ mod test { } } } + + #[test] + fn test_len() { + let su3 = Su3Adjoint::new(nalgebra::SVector::::zeros()); + assert_eq!(Su3Adjoint::len_const(), su3.len()); + } } diff --git a/src/integrator/mod.rs b/src/integrator/mod.rs index 43224183..f0a8d7cc 100644 --- a/src/integrator/mod.rs +++ b/src/integrator/mod.rs @@ -1,20 +1,20 @@ //! Numerical integrators to carry out simulations. //! //! See [`SymplecticIntegrator`]. The simulations are done on [`LatticeStateWithEField`] -//! It also require a notion of [`SimulationStateSynchrone`] +//! It also require a notion of [`SimulationStateSynchronous`] //! and [`SimulationStateLeapFrog`]. //! -//! Even thought it is effortless to implement both [`SimulationStateSynchrone`] +//! Even thought it is effortless to implement both [`SimulationStateSynchronous`] //! and [`SimulationStateLeapFrog`]. -//! I adivce against it and implement only [`SimulationStateSynchrone`] and +//! I advice against it and implement only [`SimulationStateSynchronous`] and //! use [`super::simulation::SimulationStateLeap`] //! for leap frog states as it gives a compile time check that you did not forget -//! doing a demi steps. +//! doing a half steps. //! //! This library gives two implementations of [`SymplecticIntegrator`]: //! [`SymplecticEuler`] and [`SymplecticEulerRayon`]. //! I would advice using [`SymplecticEulerRayon`] if you do not mind the little -//! more momory it uses. +//! more memory it uses. //! # Example //! let us create a basic random state and let us simulate. //! ``` @@ -29,7 +29,7 @@ //! //! let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed //! let state1 = LatticeStateEFSyncDefault::new_random_e_state( -//! LatticeStateDefault::<3>::new_deterministe(100_f64, 1_f64, 4, &mut rng)?, +//! LatticeStateDefault::<3>::new_determinist(100_f64, 1_f64, 4, &mut rng)?, //! &mut rng, //! ); //! let integrator = SymplecticEuler::default(); @@ -51,7 +51,7 @@ //! # //! # let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed //! # let state1 = LatticeStateEFSyncDefault::new_random_e_state( -//! # LatticeStateDefault::<3>::new_deterministe(100_f64, 1_f64, 4, &mut rng)?, +//! # LatticeStateDefault::<3>::new_determinist(100_f64, 1_f64, 4, &mut rng)?, //! # &mut rng, //! # ); //! # let integrator = SymplecticEuler::default(); @@ -63,14 +63,14 @@ //! # Ok(()) //! # } //! ``` -//! See [`SimulationStateSynchrone`] for more convenient methods. +//! See [`SimulationStateSynchronous`] for more convenient methods. use na::SVector; use super::{ field::{EField, LinkMatrix, Su3Adjoint}, - lattice::{LatticeCyclique, LatticeLink, LatticeLinkCanonical, LatticePoint}, - simulation::{LatticeStateWithEField, SimulationStateLeapFrog, SimulationStateSynchrone}, + lattice::{LatticeCyclic, LatticeLink, LatticeLinkCanonical, LatticePoint}, + simulation::{LatticeStateWithEField, SimulationStateLeapFrog, SimulationStateSynchronous}, CMatrix3, Complex, Real, }; @@ -80,35 +80,25 @@ pub mod symplectic_euler_rayon; pub use symplectic_euler::SymplecticEuler; pub use symplectic_euler_rayon::SymplecticEulerRayon; -/* -/// Define an numerical integrator -pub trait Integrator - where State: LatticeStateWithEField, - State2: LatticeStateWithEField, -{ - /// Do one simulation step - fn integrate(&self, l: &State, delta_t: Real) -> Result; -} -*/ - /// Define an symplectic numerical integrator /// -/// The integrator evlove the state in time. +/// The integrator evolve the state in time. /// /// The integrator should be capable of switching between Sync state /// (q (or link matrices) at time T , p (or e_field) at time T ) /// and leap frog (a at time T, p at time T + 1/2) /// +/// # Example /// For an example see the module level documentation [`super::integrator`]. pub trait SymplecticIntegrator where - StateSync: SimulationStateSynchrone, + StateSync: SimulationStateSynchronous, StateLeap: SimulationStateLeapFrog, { /// Type of error returned by the Integrator. type Error; - /// Integrate a sync state to a sync state by advaning the link matrices and the electrical field simultaneously. + /// Integrate a sync state to a sync state by advancing the link matrices and the electrical field simultaneously. /// /// # Example /// see the module level documentation [`super::integrator`]. @@ -133,7 +123,7 @@ where /// /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed /// let state = LatticeStateEFSyncDefault::new_random_e_state( - /// LatticeStateDefault::<3>::new_deterministe(1_f64, 2_f64, 4, &mut rng)?, + /// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, /// &mut rng, /// ); /// let h = state.hamiltonian_total(); @@ -176,7 +166,7 @@ where fn integrate_leap_sync(&self, l: &StateLeap, delta_t: Real) -> Result; /// Integrate a Sync state by going to leap and then back to sync. - /// This is the symplectic methode of integration, which should conserve approximately the hamiltonian + /// This is the symplectic method of integration, which should conserve approximately the hamiltonian /// /// Note that you might want to override this method as it can save you from a clone. /// @@ -193,7 +183,7 @@ where /// /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed /// let mut state = LatticeStateEFSyncDefault::new_random_e_state( - /// LatticeStateDefault::<3>::new_deterministe(1_f64, 2_f64, 4, &mut rng)?, + /// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, /// &mut rng, /// ); /// let h = state.hamiltonian_total(); @@ -217,16 +207,17 @@ where } } -/// function for link intregration. -/// This must suceed as it is use while doing parallel computation. Returning a Option is undesirable. +/// function for link integration. +/// This must succeed as it is use while doing parallel computation. Returning a Option is undesirable. /// As it can panic if a out of bound link is passed it needs to stay private. +/// /// # Panic /// It panics if a out of bound link is passed. fn integrate_link( link: &LatticeLinkCanonical, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> CMatrix3 where @@ -241,15 +232,16 @@ where * Complex::from(delta_t) } -/// function for "Electrical" field intregration. -/// Like [`integrate_link`] this must suceed. +/// function for "Electrical" field integration. +/// Like [`integrate_link`] this must succeed. +/// /// # Panics /// It panics if a out of bound link is passed. fn integrate_efield( point: &LatticePoint, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> SVector where diff --git a/src/integrator/symplectic_euler.rs b/src/integrator/symplectic_euler.rs index 8a1a4dfc..5e4df801 100644 --- a/src/integrator/symplectic_euler.rs +++ b/src/integrator/symplectic_euler.rs @@ -11,10 +11,10 @@ use serde::{Deserialize, Serialize}; use super::{ super::{ field::{EField, LinkMatrix, Su3Adjoint}, - lattice::LatticeCyclique, + lattice::LatticeCyclic, simulation::{ LatticeState, LatticeStateWithEField, LatticeStateWithEFieldNew, SimulationStateLeap, - SimulationStateSynchrone, + SimulationStateSynchronous, }, thread::{run_pool_parallel_vec, ThreadError}, CMatrix3, Real, @@ -58,7 +58,7 @@ impl std::error::Error for SymplecticEulerEr /// Basic symplectic Euler integrator /// -/// slightly slower than [`super::SymplecticEulerRayon`] (for aproriate choice of `number_of_thread`) +/// slightly slower than [`super::SymplecticEulerRayon`] (for appropriate choice of `number_of_thread`) /// but use less memory /// /// For an example see the module level documentation [`super`]. @@ -85,7 +85,7 @@ impl SymplecticEuler { self, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> Result, ThreadError> where @@ -109,7 +109,7 @@ impl SymplecticEuler { self, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> Result>, ThreadError> where @@ -151,7 +151,7 @@ impl std::fmt::Display for SymplecticEuler { impl SymplecticIntegrator, D> for SymplecticEuler where - State: SimulationStateSynchrone + LatticeStateWithEField + LatticeStateWithEFieldNew, + State: SimulationStateSynchronous + LatticeStateWithEField + LatticeStateWithEFieldNew, { type Error = SymplecticEulerError; @@ -235,7 +235,7 @@ where l.lattice(), delta_t, )?); - // we advace the counter by one + // we advance the counter by one let e_field = EField::new(self.e_field_integrate::( &link_matrix, l.e_field(), @@ -256,7 +256,7 @@ where // override for optimization. // This remove a clone operation. - let e_field_demi = EField::new(self.e_field_integrate::( + let e_field_half = EField::new(self.e_field_integrate::( l.link_matrix(), l.e_field(), l.lattice(), @@ -264,13 +264,13 @@ where )?); let link_matrix = LinkMatrix::new(self.link_matrix_integrate::( l.link_matrix(), - &e_field_demi, + &e_field_half, l.lattice(), delta_t, )?); let e_field = EField::new(self.e_field_integrate::( &link_matrix, - &e_field_demi, + &e_field_half, l.lattice(), delta_t / 2_f64, )?); diff --git a/src/integrator/symplectic_euler_rayon.rs b/src/integrator/symplectic_euler_rayon.rs index 5e0896c7..0b887029 100644 --- a/src/integrator/symplectic_euler_rayon.rs +++ b/src/integrator/symplectic_euler_rayon.rs @@ -9,10 +9,10 @@ use serde::{Deserialize, Serialize}; use super::{ super::{ field::{EField, LinkMatrix, Su3Adjoint}, - lattice::LatticeCyclique, + lattice::LatticeCyclic, simulation::{ LatticeState, LatticeStateWithEField, LatticeStateWithEFieldNew, SimulationStateLeap, - SimulationStateSynchrone, + SimulationStateSynchronous, }, thread::run_pool_parallel_rayon, Real, @@ -36,7 +36,7 @@ use super::{ /// /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed /// let state1 = LatticeStateEFSyncDefault::new_random_e_state( -/// LatticeStateDefault::<3>::new_deterministe(1_f64, 2_f64, 4, &mut rng)?, +/// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, /// &mut rng, /// ); /// let integrator = SymplecticEulerRayon::default(); @@ -57,7 +57,7 @@ impl SymplecticEulerRayon { Self {} } - /// Get all the intregrated links + /// Get all the integrated links /// # Panics /// panics if the lattice has fewer link than link_matrix has or it has fewer point than e_field has. /// In debug panic if the lattice has not the same number link as link_matrix @@ -65,7 +65,7 @@ impl SymplecticEulerRayon { fn link_matrix_integrate( link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> Vec where @@ -80,7 +80,7 @@ impl SymplecticEulerRayon { ) } - /// Get all the intregrated e field + /// Get all the integrated e field /// # Panics /// panics if the lattice has fewer link than link_matrix has or it has fewer point than e_field has. /// In debug panic if the lattice has not the same number link as link_matrix @@ -88,7 +88,7 @@ impl SymplecticEulerRayon { fn e_field_integrate( link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, delta_t: Real, ) -> Vec> where @@ -120,7 +120,7 @@ impl std::fmt::Display for SymplecticEulerRayon { impl SymplecticIntegrator, D> for SymplecticEulerRayon where - State: SimulationStateSynchrone + LatticeStateWithEField + LatticeStateWithEFieldNew, + State: SimulationStateSynchronous + LatticeStateWithEField + LatticeStateWithEFieldNew, { type Error = State::Error; @@ -182,7 +182,7 @@ where delta_t / 2_f64, ); - // we do not advace the time counter + // we do not advance the time counter SimulationStateLeap::::new( l.lattice().clone(), l.beta(), @@ -203,7 +203,7 @@ where l.lattice(), delta_t, )); - // we advace the counter by one + // we advance the counter by one let e_field = EField::new(Self::e_field_integrate::( &link_matrix, l.e_field(), @@ -223,7 +223,7 @@ where // override for optimization. // This remove a clone operation. - let e_field_demi = EField::new(Self::e_field_integrate::( + let e_field_half = EField::new(Self::e_field_integrate::( l.link_matrix(), l.e_field(), l.lattice(), @@ -231,13 +231,13 @@ where )); let link_matrix = LinkMatrix::new(Self::link_matrix_integrate::( l.link_matrix(), - &e_field_demi, + &e_field_half, l.lattice(), delta_t, )); let e_field = EField::new(Self::e_field_integrate::( &link_matrix, - &e_field_demi, + &e_field_half, l.lattice(), delta_t / 2_f64, )); diff --git a/src/lattice.rs b/src/lattice.rs index 636a3d6c..ac234c2b 100644 --- a/src/lattice.rs +++ b/src/lattice.rs @@ -1,8 +1,9 @@ //! Defines lattices and lattice component. //! -//! [`LatticeCyclique`] is the structure that encode the lattice information like +//! [`LatticeCyclic`] is the structure that encode the lattice information like //! the lattice spacing, the number of point and the dimension. -//! It is used to do operation on [`LatticePoint`], [`LatticeLink`] and [`LatticeLinkCanonical`]. +//! It is used to do operation on [`LatticePoint`], [`LatticeLink`] and +//! [`LatticeLinkCanonical`]. //! Or to get an iterator over these elements. //! //! [`LatticePoint`], [`LatticeLink`] and [`LatticeLinkCanonical`] are elements on the lattice. @@ -21,36 +22,36 @@ use serde::{Deserialize, Serialize}; use super::field::{EField, LinkMatrix}; use super::{error::LatticeInitializationError, Real}; -/// A cyclique lattice in space. Does not store point and links but is used to generate them. +/// A Cyclic lattice in space. Does not store point and links but is used to generate them. /// /// The generic parameter `D` is the dimension. /// -/// This lattice is cyclique more precisely if the lattice has N poits in each direction. -/// Then we can mouve alongisde a direction going though point 0, 1, ... N-1. The next step in +/// This lattice is Cyclic more precisely if the lattice has N points in each direction. +/// Then we can move alongside a direction going though point 0, 1, ... N-1. The next step in /// the same direction goes back to the point at 0. /// /// This structure is used for operation on [`LatticePoint`], [`LatticeLink`] and /// [`LatticeLinkCanonical`]. // For example, theses three structures are abstract and are in general use to /// access data on the lattice. These data are stored [`LinkMatrix`] and [`EField`] which are just -/// a wrapper arround a [`Vec`]. `LatticeCyclique` is used to convert thes lattice element to +/// a wrapper around a [`Vec`]. `LatticeCyclic` is used to convert the lattice element to /// an index to access these data. /// /// This contain very few data and can be cloned at almost no cost even though /// it does not implement [`Copy`]. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -pub struct LatticeCyclique { +pub struct LatticeCyclic { /// The lattice spacing. size: Real, /// The number of point *per* dimension. dim: usize, } -impl LatticeCyclique { +impl LatticeCyclic { /// Number space + time dimension, this is the `D` parameter. /// - /// Not to confuse with [`LatticeCyclique::dim`] which is the number of point per dimension. + /// Not to confuse with [`LatticeCyclic::dim`] which is the number of point per dimension. pub const fn dim_st() -> usize { D } @@ -60,21 +61,25 @@ impl LatticeCyclique { /// the link return is `[x - 1, y, z, t]` (modulo the `lattice::dim()``) with direction `+x` /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{LatticeCyclique, DirectionEnum, LatticePoint, LatticeLinkCanonical}; - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4).unwrap(); + /// # use lattice_qcd_rs::lattice::{LatticeCyclic, DirectionEnum, LatticePoint, LatticeLinkCanonical}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// fn main() -> Result<(), Box> { + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; /// let point = LatticePoint::<4>::new([1, 0, 2, 0].into()); /// assert_eq!( /// lattice.link_canonical(point, DirectionEnum::XNeg.into()), - /// LatticeLinkCanonical::new(LatticePoint::new([0, 0, 2, 0].into()), DirectionEnum::XPos.into()).unwrap() + /// LatticeLinkCanonical::new(LatticePoint::new([0, 0, 2, 0].into()), DirectionEnum::XPos.into()).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); /// assert_eq!( /// lattice.link_canonical(point, DirectionEnum::XPos.into()), - /// LatticeLinkCanonical::new(LatticePoint::new([1, 0, 2, 0].into()), DirectionEnum::XPos.into()).unwrap() + /// LatticeLinkCanonical::new(LatticePoint::new([1, 0, 2, 0].into()), DirectionEnum::XPos.into()).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); /// assert_eq!( /// lattice.link_canonical(point, DirectionEnum::YNeg.into()), - /// LatticeLinkCanonical::new(LatticePoint::new([1, 3, 2, 0].into()), DirectionEnum::YPos.into()).unwrap() + /// LatticeLinkCanonical::new(LatticePoint::new([1, 3, 2, 0].into()), DirectionEnum::YPos.into()).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); + /// # Ok(()) + /// # } /// ``` pub fn link_canonical( &self, @@ -97,16 +102,19 @@ impl LatticeCyclique { /// If it is not, it will use the modulus of the bound. /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{LatticeCyclique, Direction, LatticePoint}; + /// # use lattice_qcd_rs::{lattice::{LatticeCyclic, Direction, LatticePoint}, error::ImplementationError}; /// # use nalgebra::SVector; - /// let l = LatticeCyclique::<3>::new(1_f64, 4).unwrap(); - /// let dir = Direction::new(0, true).unwrap(); + /// fn main() -> Result<(), Box> { + /// let l = LatticeCyclic::<3>::new(1_f64, 4)?; + /// let dir = Direction::new(0, true).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// let pt = LatticePoint::new(SVector::<_, 3>::new(1, 2, 5)); /// let link = l.link(pt, dir); /// assert_eq!( /// *link.pos(), /// LatticePoint::new(SVector::<_, 3>::new(1, 2, 1)) /// ); + /// # Ok(()) + /// # } /// ``` pub fn link(&self, pos: LatticePoint, dir: Direction) -> LatticeLink { let mut pos_link = LatticePoint::new_zero(); @@ -118,25 +126,52 @@ impl LatticeCyclique { /// Transform a [`LatticeLink`] into a [`LatticeLinkCanonical`]. /// - /// See [`LatticeCyclique::link_canonical`] and [`LatticeLinkCanonical`]. + /// See [`LatticeCyclic::link_canonical`] and [`LatticeLinkCanonical`]. pub fn into_canonical(&self, l: LatticeLink) -> LatticeLinkCanonical { self.link_canonical(*l.pos(), *l.dir()) } /// Get the number of points in a single direction. /// - /// use [`LatticeCyclique::number_of_points`] for the total number of points. - /// Not to confuse with [`LatticeCyclique::dim_st`] which is the dimension of space-time. + /// use [`LatticeCyclic::number_of_points`] for the total number of points. + /// Not to confuse with [`LatticeCyclic::dim_st`] which is the dimension of space-time. pub const fn dim(&self) -> usize { self.dim } /// Get an Iterator over all points of the lattice. + /// + /// # Example + /// ``` + /// # use lattice_qcd_rs::lattice::LatticeCyclic; + /// # fn main() -> Result<(), Box> { + /// for i in [4, 8, 16, 32, 64].into_iter() { + /// let l = LatticeCyclic::<4>::new(1_f64, i)?; + /// assert_eq!(l.get_points().size_hint().0, l.number_of_points()); + /// } + /// # Ok(()) + /// # } + /// ``` pub fn get_points(&self) -> IteratorLatticePoint<'_, D> { IteratorLatticePoint::new(self, LatticePoint::new_zero()) } /// Get an Iterator over all canonical link of the lattice. + /// + /// # Example + /// ``` + /// # use lattice_qcd_rs::lattice::LatticeCyclic; + /// # fn main() -> Result<(), Box> { + /// for i in [4, 8, 16, 32, 64].into_iter() { + /// let l = LatticeCyclic::<4>::new(1_f64, i)?; + /// assert_eq!( + /// l.get_links().size_hint().0, + /// l.number_of_canonical_links_space() + /// ); + /// } + /// # Ok(()) + /// # } + /// ``` pub fn get_links(&self) -> IteratorLatticeLinkCanonical<'_, D> { return IteratorLatticeLinkCanonical::new( self, @@ -149,6 +184,7 @@ impl LatticeCyclique { /// create a new lattice with `size` the lattice size parameter, and `dim` the number of /// points in each spatial dimension. + /// /// # Errors /// Size should be greater than 0 and dim greater or equal to 2, otherwise return an error. pub fn new(size: Real, dim: usize) -> Result { @@ -166,12 +202,44 @@ impl LatticeCyclique { /// Total number of canonical links oriented in space for a set time. /// - /// basically the number of element return by [`LatticeCyclique::get_links`] + /// Basically the number of element return by [`LatticeCyclic::get_links`]. + /// + /// # Example + /// ``` + /// # use lattice_qcd_rs::lattice::LatticeCyclic; + /// # fn main() -> Result<(), Box> { + /// let l = LatticeCyclic::<4>::new(1_f64, 8)?; + /// assert_eq!(l.number_of_canonical_links_space(), 8_usize.pow(4) * 4); + /// + /// let l = LatticeCyclic::<4>::new(1_f64, 16)?; + /// assert_eq!(l.number_of_canonical_links_space(), 16_usize.pow(4) * 4); + /// + /// let l = LatticeCyclic::<3>::new(1_f64, 8)?; + /// assert_eq!(l.number_of_canonical_links_space(), 8_usize.pow(3) * 3); + /// # Ok(()) + /// # } + /// ``` pub fn number_of_canonical_links_space(&self) -> usize { self.number_of_points() * D } /// Total number of point in the lattice for a set time. + /// + /// # Example + /// ``` + /// # use lattice_qcd_rs::lattice::LatticeCyclic; + /// # fn main() -> Result<(), Box> { + /// let l = LatticeCyclic::<4>::new(1_f64, 8)?; + /// assert_eq!(l.number_of_points(), 8_usize.pow(4)); + /// + /// let l = LatticeCyclic::<4>::new(1_f64, 16)?; + /// assert_eq!(l.number_of_points(), 16_usize.pow(4)); + /// + /// let l = LatticeCyclic::<3>::new(1_f64, 8)?; + /// assert_eq!(l.number_of_points(), 8_usize.pow(3)); + /// # Ok(()) + /// # } + /// ``` pub fn number_of_points(&self) -> usize { self.dim().pow(D.try_into().unwrap()) } @@ -181,23 +249,26 @@ impl LatticeCyclique { self.size } - /// get the next point in the lattice following the direction `dir`. - /// It follows the cyclique property of the lattice. + /// Get the next point in the lattice following the direction `dir`. + /// It follows the Cyclic property of the lattice. /// /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{LatticeCyclique, DirectionEnum, LatticePoint}; - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4).unwrap(); + /// # use lattice_qcd_rs::lattice::{LatticeCyclic, DirectionEnum, LatticePoint}; + /// # fn main() -> Result<(), Box> { + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; /// let point = LatticePoint::<4>::from([1, 0, 2, 0]); /// assert_eq!( /// lattice.add_point_direction(point, &DirectionEnum::XPos.into()), /// LatticePoint::from([2, 0, 2, 0]) /// ); - /// // In the following case we get [_, 3, _, _] because `dim = 4`, and this lattice is cyclique. + /// // In the following case we get [_, 3, _, _] because `dim = 4`, and this lattice is Cyclic. /// assert_eq!( /// lattice.add_point_direction(point, &DirectionEnum::YNeg.into()), /// LatticePoint::from([1, 3, 2, 0]) /// ); + /// # Ok(()) + /// # } /// ``` pub fn add_point_direction( &self, @@ -207,24 +278,27 @@ impl LatticeCyclique { self.add_point_direction_n(point, dir, 1) } - /// Returns the point given y mouving `shift_number` times in direction `dir` from position `point`. - /// It follows the cyclique property of the lattice. + /// Returns the point given y moving `shift_number` times in direction `dir` from position `point`. + /// It follows the Cyclic property of the lattice. /// /// It is equivalent of doing [`Self::add_point_direction`] n times. /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{LatticeCyclique, DirectionEnum, LatticePoint}; - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4).unwrap(); + /// # use lattice_qcd_rs::lattice::{LatticeCyclic, DirectionEnum, LatticePoint}; + /// # fn main() -> Result<(), Box> { + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; /// let point = LatticePoint::<4>::from([1, 0, 2, 0]); /// assert_eq!( /// lattice.add_point_direction_n(point, &DirectionEnum::XPos.into(), 2), /// LatticePoint::from([3, 0, 2, 0]) /// ); - /// // In the following case we get [_, 1, _, _] because `dim = 4`, and this lattice is cyclique. + /// // In the following case we get [_, 1, _, _] because `dim = 4`, and this lattice is Cyclic. /// assert_eq!( /// lattice.add_point_direction_n(point, &DirectionEnum::YNeg.into(), 3), /// LatticePoint::from([1, 1, 2, 0]) /// ); + /// # Ok(()) + /// # } /// ``` pub fn add_point_direction_n( &self, @@ -248,37 +322,37 @@ impl LatticeCyclique { point } - /// Retuns whether the number of canonical link is the same as the length of `links` - pub fn has_compatible_lenght_links(&self, links: &LinkMatrix) -> bool { + /// Returns whether the number of canonical link is the same as the length of `links`. + pub fn has_compatible_length_links(&self, links: &LinkMatrix) -> bool { self.number_of_canonical_links_space() == links.len() } - /// Returns wether the number of point is the same as the length of `e_field` - pub fn has_compatible_lenght_e_field(&self, e_field: &EField) -> bool { + /// Returns wether the number of point is the same as the length of `e_field`. + pub fn has_compatible_length_e_field(&self, e_field: &EField) -> bool { self.number_of_points() == e_field.len() } - /// Retuns the length is compatible for both `links` and `e_field`. - /// See [`Self::has_compatible_lenght_links`] and [`Self::has_compatible_lenght_e_field`]. - pub fn has_compatible_lenght(&self, links: &LinkMatrix, e_field: &EField) -> bool { - self.has_compatible_lenght_links(links) && self.has_compatible_lenght_e_field(e_field) + /// Returns the length is compatible for both `links` and `e_field`. + /// See [`Self::has_compatible_length_links`] and [`Self::has_compatible_length_e_field`]. + pub fn has_compatible_length(&self, links: &LinkMatrix, e_field: &EField) -> bool { + self.has_compatible_length_links(links) && self.has_compatible_length_e_field(e_field) } } -impl std::fmt::Display for LatticeCyclique { +impl std::fmt::Display for LatticeCyclic { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "cyclique lattice with {}^{} points and spacing {}", + "Cyclic lattice with {}^{} points and spacing {}", self.dim, D, self.size ) } } -/// Iterator over [`LatticeLinkCanonical`] associated to a particular [`LatticeCyclique`]. +/// Iterator over [`LatticeLinkCanonical`] associated to a particular [`LatticeCyclic`]. #[derive(Clone, Debug, PartialEq)] pub struct IteratorLatticeLinkCanonical<'a, const D: usize> { - lattice: &'a LatticeCyclique, + lattice: &'a LatticeCyclic, element: Option>, } @@ -286,13 +360,17 @@ impl<'a, const D: usize> IteratorLatticeLinkCanonical<'a, D> { /// create a new iterator. The first [`IteratorLatticeLinkCanonical::next()`] will return `first_el`. /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{IteratorLatticeLinkCanonical, LatticeCyclique, LatticeLinkCanonical, LatticePoint, DirectionEnum}; - /// let lattice = LatticeCyclique::<4>::new(1_f64, 4).unwrap(); - /// let first_el = LatticeLinkCanonical::<4>::new(LatticePoint::from([1, 0, 2, 0]), DirectionEnum::YPos.into()).unwrap(); + /// # use lattice_qcd_rs::lattice::{IteratorLatticeLinkCanonical, LatticeCyclic, LatticeLinkCanonical, LatticePoint, DirectionEnum}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { + /// let lattice = LatticeCyclic::<4>::new(1_f64, 4)?; + /// let first_el = LatticeLinkCanonical::<4>::new(LatticePoint::from([1, 0, 2, 0]), DirectionEnum::YPos.into()).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// let mut iter = IteratorLatticeLinkCanonical::new(&lattice, first_el); - /// assert_eq!(iter.next().unwrap(), first_el); + /// assert_eq!(iter.next().ok_or(ImplementationError::OptionWithUnexpectedNone)?, first_el); + /// # Ok(()) + /// # } /// ``` - pub const fn new(lattice: &'a LatticeCyclique, first_el: LatticeLinkCanonical) -> Self { + pub const fn new(lattice: &'a LatticeCyclic, first_el: LatticeLinkCanonical) -> Self { Self { lattice, element: Some(first_el), @@ -315,7 +393,7 @@ impl<'a, const D: usize> Iterator for IteratorLatticeLinkCanonical<'a, D> { element.set_dir(Direction::new(0, true).unwrap()); let mut iter = IteratorLatticePoint::new(self.lattice, *element.pos()); match iter.nth(1) { - // get the second ellement + // get the second element Some(array) => *element.pos_mut() = array, None => { self.element = None; @@ -344,7 +422,7 @@ impl<'a, const D: usize> FusedIterator for IteratorLatticeLinkCanonical<'a, D> { impl<'a, const D: usize> ExactSizeIterator for IteratorLatticeLinkCanonical<'a, D> {} -/// Enum for internal use of interator. It store the previous element returned by `next` +/// Enum for internal use of iterator. It store the previous element returned by `next` #[derive(Clone, Debug, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum IteratorElement { @@ -352,7 +430,7 @@ pub enum IteratorElement { FirstElement, /// An element of the iterator Element(T), - /// The Iterator is exausted + /// The Iterator is exhausted LastElement, } @@ -385,13 +463,34 @@ impl From> for Option { /// # Example /// ``` /// # use lattice_qcd_rs::lattice::{IteratorDirection, Direction, IteratorElement}; -/// let mut iter = IteratorDirection::<4, true>::new(None).unwrap(); -/// assert_eq!(iter.next().unwrap(), Direction::new(0, true).unwrap()); -/// assert_eq!(iter.next().unwrap(), Direction::new(1, true).unwrap()); -/// assert_eq!(iter.next().unwrap(), Direction::new(2, true).unwrap()); -/// assert_eq!(iter.next().unwrap(), Direction::new(3, true).unwrap()); +/// # use lattice_qcd_rs::error::ImplementationError; +/// # fn main() -> Result<(), Box> { +/// let mut iter = IteratorDirection::<4, true>::new(None) +/// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; +/// assert_eq!( +/// iter.next() +/// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, +/// Direction::new(0, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? +/// ); +/// assert_eq!( +/// iter.next() +/// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, +/// Direction::new(1, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? +/// ); +/// assert_eq!( +/// iter.next() +/// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, +/// Direction::new(2, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? +/// ); +/// assert_eq!( +/// iter.next() +/// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, +/// Direction::new(3, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? +/// ); /// assert_eq!(iter.next(), None); /// assert_eq!(iter.next(), None); +/// # Ok(()) +/// # } /// ``` #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -407,22 +506,51 @@ impl /// # Example /// ``` /// # use lattice_qcd_rs::lattice::{IteratorDirection, Direction, IteratorElement}; - /// let mut iter = IteratorDirection::<4, true>::new(None).unwrap(); - /// assert_eq!(iter.next().unwrap(), Direction::new(0, true).unwrap()); - /// assert_eq!(iter.next().unwrap(), Direction::new(1, true).unwrap()); - /// let element = Direction::<4>::new(0, false).unwrap(); - /// let mut iter = IteratorDirection::<4, false>::new(Some(element)).unwrap(); - /// assert_eq!(iter.next().unwrap(), Direction::new(1, false).unwrap()); - /// assert_eq!(iter.next().unwrap(), Direction::new(2, false).unwrap()); + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { + /// let mut iter = IteratorDirection::<4, true>::new(None) + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(0, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(1, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// let element = + /// Direction::<4>::new(0, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// let mut iter = IteratorDirection::<4, false>::new(Some(element)) + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(2, false).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// # Ok(()) + /// # } /// ``` /// ``` /// # use lattice_qcd_rs::lattice::{IteratorDirection, Direction, IteratorElement}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { /// let iter = IteratorDirection::<0, true>::new(None); - /// // 0 is invalide + /// // 0 is invalid /// assert!(iter.is_none()); - /// let iter = IteratorDirection::<4, true>::new(Some(Direction::new(2, false).unwrap())); + /// let iter = IteratorDirection::<4, true>::new(Some( + /// Direction::new(2, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// )); /// // the sign of the direction is invalid /// assert!(iter.is_none()); + /// # Ok(()) + /// # } /// ``` pub const fn new(element: Option>) -> Option { match element { @@ -432,19 +560,41 @@ impl } /// create a new iterator. The first [`IteratorLatticeLinkCanonical::next()`] the element just after the one given - /// or the first ellement if [`IteratorElement::FirstElement`] is given. + /// or the first element if [`IteratorElement::FirstElement`] is given. /// # Example /// ``` /// # use lattice_qcd_rs::lattice::{IteratorDirection, Direction, IteratorElement}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { + /// let mut iter = IteratorDirection::<4, true>::new_from_element(IteratorElement::FirstElement) + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(0, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(1, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// let element = + /// Direction::<4>::new(0, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// let mut iter = - /// IteratorDirection::<4, true>::new_from_element(IteratorElement::FirstElement).unwrap(); - /// assert_eq!(iter.next().unwrap(), Direction::new(0, true).unwrap()); - /// assert_eq!(iter.next().unwrap(), Direction::new(1, true).unwrap()); - /// let element = Direction::<4>::new(0, false).unwrap(); - /// let mut iter = - /// IteratorDirection::<4, false>::new_from_element(IteratorElement::Element(element)).unwrap(); - /// assert_eq!(iter.next().unwrap(), Direction::new(1, false).unwrap()); - /// assert_eq!(iter.next().unwrap(), Direction::new(2, false).unwrap()); + /// IteratorDirection::<4, false>::new_from_element(IteratorElement::Element(element)) + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// assert_eq!( + /// iter.next() + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?, + /// Direction::new(2, false).ok_or(ImplementationError::OptionWithUnexpectedNone)? + /// ); + /// # Ok(()) + /// # } /// ``` pub const fn new_from_element(element: IteratorElement>) -> Option { if D == 0 { @@ -506,7 +656,7 @@ impl ExactSizeIterator /// Iterator over [`LatticePoint`] #[derive(Clone, Debug, PartialEq)] pub struct IteratorLatticePoint<'a, const D: usize> { - lattice: &'a LatticeCyclique, + lattice: &'a LatticeCyclic, element: Option>, } @@ -514,13 +664,17 @@ impl<'a, const D: usize> IteratorLatticePoint<'a, D> { /// create a new iterator. The first [`IteratorLatticePoint::next()`] will return `first_el`. /// # Example /// ``` - /// # use lattice_qcd_rs::lattice::{IteratorLatticePoint, LatticeCyclique, LatticePoint, Direction}; - /// let lattice = LatticeCyclique::new(1_f64, 4).unwrap(); + /// # use lattice_qcd_rs::lattice::{IteratorLatticePoint, LatticeCyclic, LatticePoint, Direction}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { + /// let lattice = LatticeCyclic::new(1_f64, 4)?; /// let first_el = LatticePoint::from([1, 0, 2, 0]); /// let mut iter = IteratorLatticePoint::new(&lattice, first_el); - /// assert_eq!(iter.next().unwrap(), first_el); + /// assert_eq!(iter.next().ok_or(ImplementationError::OptionWithUnexpectedNone)?, first_el); + /// # Ok(()) + /// # } /// ``` - pub const fn new(lattice: &'a LatticeCyclique, first_el: LatticePoint) -> Self { + pub const fn new(lattice: &'a LatticeCyclic, first_el: LatticePoint) -> Self { Self { lattice, element: Some(first_el), @@ -539,7 +693,7 @@ impl<'a, const D: usize> Iterator for IteratorLatticePoint<'a, D> { for i in 0..el.len() { while el[i] >= self.lattice.dim() { if i < el.len() - 1 { - // every element exept the last one + // every element except the last one el[i + 1] += 1; } else { @@ -749,11 +903,11 @@ impl AsMut> for LatticePoint { // TODO change name ? make it less confusing pub trait LatticeElementToIndex { /// Given a lattice return an index from the element - fn to_index(&self, l: &LatticeCyclique) -> usize; + fn to_index(&self, l: &LatticeCyclic) -> usize; } impl LatticeElementToIndex for LatticePoint { - fn to_index(&self, l: &LatticeCyclique) -> usize { + fn to_index(&self, l: &LatticeCyclic) -> usize { self.iter() .enumerate() .map(|(index, pos)| (pos % l.dim()) * l.dim().pow(index.try_into().unwrap())) @@ -763,24 +917,24 @@ impl LatticeElementToIndex for LatticePoint { impl LatticeElementToIndex for Direction { /// equivalent to [`Direction::to_index()`] - fn to_index(&self, _: &LatticeCyclique) -> usize { + fn to_index(&self, _: &LatticeCyclic) -> usize { self.index() } } impl LatticeElementToIndex for LatticeLinkCanonical { - fn to_index(&self, l: &LatticeCyclique) -> usize { + fn to_index(&self, l: &LatticeCyclic) -> usize { self.pos().to_index(l) * D + self.dir().index() } } -/// This is juste the identity. +/// This is just the identity. /// /// It is implemented for compatibility reason /// such that function that require a [`LatticeElementToIndex`] can also accept [`usize`]. impl LatticeElementToIndex for usize { /// return self - fn to_index(&self, _l: &LatticeCyclique) -> usize { + fn to_index(&self, _l: &LatticeCyclic) -> usize { *self } } @@ -788,11 +942,11 @@ impl LatticeElementToIndex for usize { /// A canonical link of a lattice. It contain a position and a direction. /// /// The direction should always be positive. -/// By itself the link does not store data about the lattice. Hence most function require a [`LatticeCyclique`]. +/// By itself the link does not store data about the lattice. Hence most function require a [`LatticeCyclic`]. /// It also means that there is no guarantee that the object is inside a lattice. /// You can use modulus over the elements to use inside a lattice. /// -/// This object can be used to safly index in a [`std::collections::HashMap`] +/// This object can be used to safely index in a [`std::collections::HashMap`] #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct LatticeLinkCanonical { @@ -803,8 +957,9 @@ pub struct LatticeLinkCanonical { impl LatticeLinkCanonical { /// Try create a LatticeLinkCanonical. If the dir is negative it fails. /// - /// To guaranty creating an element see [LatticeCyclique::link_canonical]. + /// To guaranty creating an element see [LatticeCyclic::link_canonical]. /// The creation of an element this ways does not guaranties that the element is inside a lattice. + /// /// # Example /// ``` /// # use lattice_qcd_rs::lattice::{LatticeLinkCanonical, LatticePoint, DirectionEnum}; @@ -837,21 +992,31 @@ impl LatticeLinkCanonical { } /// Set the direction to dir + /// /// # Example /// ``` /// # use lattice_qcd_rs::lattice::{LatticeLinkCanonical, LatticePoint, DirectionEnum}; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { /// let mut lattice_link_canonical = /// LatticeLinkCanonical::new(LatticePoint::new([0; 4].into()), DirectionEnum::YPos.into()) - /// .unwrap(); + /// .ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// lattice_link_canonical.set_dir(DirectionEnum::XPos.into()); /// assert_eq!(*lattice_link_canonical.dir(), DirectionEnum::XPos.into()); + /// # Ok(()) + /// # } /// ``` + /// /// # Panic /// panic if a negative direction is given. /// ```should_panic /// # use lattice_qcd_rs::lattice::{LatticeLinkCanonical, LatticePoint, DirectionEnum}; - /// # let mut lattice_link_canonical = LatticeLinkCanonical::new(LatticePoint::new([0; 4].into()), DirectionEnum::XPos.into()).unwrap(); - /// lattice_link_canonical.set_dir(DirectionEnum::XNeg.into()); + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box> { + /// # let mut lattice_link_canonical = LatticeLinkCanonical::new(LatticePoint::new([0; 4].into()), DirectionEnum::XPos.into()).ok_or(ImplementationError::OptionWithUnexpectedNone)?; + /// lattice_link_canonical.set_dir(DirectionEnum::XNeg.into()); // Panics ! + /// # Ok(()) + /// # } /// ``` pub fn set_dir(&mut self, dir: Direction) { if dir.is_negative() { @@ -896,7 +1061,7 @@ impl From<&LatticeLinkCanonical> for LatticeLink { /// This means that multiple link can be equivalent but does not have the same data /// and therefore hash (hopefully). /// -/// By itself the link does not store data about the lattice. Hence most function require a [`LatticeCyclique`]. +/// By itself the link does not store data about the lattice. Hence most function require a [`LatticeCyclic`]. /// It also means that there is no guarantee that the object is inside a lattice. /// You can use modulus over the elements to use inside a lattice. #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] @@ -970,7 +1135,7 @@ impl Direction { } /// List of all positives directions. - /// This is very slow use [`Self::positive_directions`] instead + /// This is very slow use [`Self::positive_directions`] instead. pub fn positives_vec() -> Vec { let mut x = Vec::with_capacity(D); for i in 0..D { @@ -980,7 +1145,7 @@ impl Direction { } /// List all directions. - /// This is very slow use [`DirectionList::directions`] instead + /// This is very slow use [`DirectionList::directions`] instead. pub fn directions_vec() -> Vec { let mut x = Vec::with_capacity(2 * D); for i in 0..D { @@ -991,7 +1156,7 @@ impl Direction { } // TODO add const function for all direction once operation on const generic are added - /// Get all direction with the sign `IS_POSITIVE` + /// Get all direction with the sign `IS_POSITIVE`. pub const fn directions_array() -> [Self; D] { // TODO use unsafe code to avoid the allocation let mut i = 0_usize; @@ -1080,19 +1245,22 @@ impl Direction { /// # Example /// ``` /// # use lattice_qcd_rs::lattice::Direction; - /// # extern crate nalgebra; + /// # use lattice_qcd_rs::error::ImplementationError; + /// # fn main() -> Result<(), Box< dyn std::error::Error>> { /// assert_eq!( /// Direction::from_vector(&nalgebra::Vector4::new(1_f64, 0_f64, 0_f64, 0_f64)), - /// Direction::<4>::new(0, true).unwrap() + /// Direction::<4>::new(0, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); /// assert_eq!( /// Direction::from_vector(&nalgebra::Vector4::new(0_f64, -1_f64, 0_f64, 0_f64)), - /// Direction::<4>::new(1, false).unwrap() + /// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); /// assert_eq!( /// Direction::from_vector(&nalgebra::Vector4::new(0.5_f64, 1_f64, 0_f64, 2_f64)), - /// Direction::<4>::new(3, true).unwrap() + /// Direction::<4>::new(3, true).ok_or(ImplementationError::OptionWithUnexpectedNone)? /// ); + /// # Ok(()) + /// # } /// ``` pub fn from_vector(v: &SVector) -> Self { let mut max = 0_f64; @@ -1110,7 +1278,7 @@ impl Direction { } } -// TODO default when condition on const generic is avaliable +// TODO default when condition on const generic is available /* impl Default for LatticeLinkCanonical @@ -1167,25 +1335,37 @@ implement_direction_from!(); /// # Example /// ``` /// # use lattice_qcd_rs::lattice::Direction; +/// # use lattice_qcd_rs::error::ImplementationError; /// use std::cmp::Ordering; +/// # fn main() -> Result<(), Box< dyn std::error::Error>> { /// -/// let dir_1 = Direction::<4>::new(1, false).unwrap(); -/// let dir_2 = Direction::<4>::new(1, true).unwrap(); +/// let dir_1 = +/// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; +/// let dir_2 = +/// Direction::<4>::new(1, true).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// assert!(dir_1 < dir_2); /// assert_eq!(dir_1.partial_cmp(&dir_2), Some(Ordering::Less)); /// //-------- -/// let dir_3 = Direction::<4>::new(3, false).unwrap(); -/// let dir_4 = Direction::<4>::new(1, false).unwrap(); +/// let dir_3 = +/// Direction::<4>::new(3, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; +/// let dir_4 = +/// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// assert!(dir_3 > dir_4); /// assert_eq!(dir_3.partial_cmp(&dir_4), Some(Ordering::Greater)); /// //-------- -/// let dir_5 = Direction::<4>::new(3, true).unwrap(); -/// let dir_6 = Direction::<4>::new(1, false).unwrap(); +/// let dir_5 = +/// Direction::<4>::new(3, true).ok_or(ImplementationError::OptionWithUnexpectedNone)?; +/// let dir_6 = +/// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// assert_eq!(dir_5.partial_cmp(&dir_6), None); /// //-------- -/// let dir_5 = Direction::<4>::new(1, false).unwrap(); -/// let dir_6 = Direction::<4>::new(1, false).unwrap(); +/// let dir_5 = +/// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; +/// let dir_6 = +/// Direction::<4>::new(1, false).ok_or(ImplementationError::OptionWithUnexpectedNone)?; /// assert_eq!(dir_5.partial_cmp(&dir_6), Some(Ordering::Equal)); +/// # Ok(()) +/// # } /// ``` impl PartialOrd for Direction { fn partial_cmp(&self, other: &Self) -> Option { @@ -1396,7 +1576,7 @@ impl DirectionEnum { /// DirectionEnum::TPos /// ); /// ``` - #[allow(clippy::needless_return)] // for lisibiliy + #[allow(clippy::needless_return)] // for readability pub fn from_vector(v: &Vector4) -> Self { let mut max = 0_f64; let mut index_max: usize = 0; @@ -1444,7 +1624,7 @@ impl DirectionEnum { } _ => { // the code should attain this code. and therefore panicking is not expected. - unreachable!("Implementiation error : invalide index") + unreachable!("Implementation error : invalid index") } } } @@ -1743,7 +1923,7 @@ mod test { assert_eq!(Direction::<4>::directions().len(), 8); assert_eq!(Direction::<4>::positive_directions().len(), 4); - let l = LatticeCyclique::new(1_f64, 4).unwrap(); + let l = LatticeCyclic::new(1_f64, 4).unwrap(); for dir in Direction::<3>::directions() { assert_eq!( as LatticeElementToIndex<3>>::to_index(dir, &l), @@ -1808,7 +1988,7 @@ mod test { #[allow(clippy::cognitive_complexity)] #[test] fn iterator() { - let l = LatticeCyclique::<2>::new(1_f64, 4).unwrap(); + let l = LatticeCyclic::<2>::new(1_f64, 4).unwrap(); let mut iterator = l.get_points(); assert_eq!( iterator.size_hint(), @@ -1882,10 +2062,10 @@ mod test { #[test] fn lattice() { - let lattice = LatticeCyclique::<3>::new(1_f64, 8).unwrap(); + let lattice = LatticeCyclic::<3>::new(1_f64, 8).unwrap(); assert_eq!( lattice.to_string(), - "cyclique lattice with 8^3 points and spacing 1" + "Cyclic lattice with 8^3 points and spacing 1" ); } } diff --git a/src/lib.rs b/src/lib.rs index 70790762..c4caa606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,7 +67,7 @@ mod test; /// alias for [`f64`] pub type Real = f64; -/// easy to use allias for [`nalgebra::Complex::`] +/// easy to use alias for [`nalgebra::Complex::`] pub type Complex = na::Complex; /// alias for [`nalgebra::SVector::`] pub type Vector8 = na::SVector; diff --git a/src/macro_def.rs b/src/macro_def.rs index 294a9f90..134f3e1c 100644 --- a/src/macro_def.rs +++ b/src/macro_def.rs @@ -31,7 +31,7 @@ //! } //! ``` //! # project! -//! project an methode on one of the composant to the structur. +//! project an methods on one of the corposant to the structure. //! ## Example //! ```ignore //! struct A{} @@ -46,7 +46,7 @@ //! } //! ``` //! # project_mut! -//! same as `project!` but with `&mut self` in the signature of the methode replacing `&sefl` +//! same as `project!` but with `&mut self` in the signature of the method replacing `&self` //! ## Example //! ```ignore //! struct A{} @@ -146,7 +146,8 @@ macro_rules! project_mut { } #[macro_export] -/// assert if two matrices are approximatively the same +/// assert if two matrices are approximately the same +// TODO example macro_rules! assert_eq_matrix { ($e:expr, $e2:expr, $epsilon:expr) => { let e = $e; @@ -161,7 +162,8 @@ macro_rules! assert_eq_matrix { } #[macro_export] -/// assert if two complex are approximatively the same +/// assert if two complex are approximately the same +// TODO example macro_rules! assert_eq_complex { ($e:expr, $e2:expr, $epsilon:expr) => { { @@ -183,6 +185,7 @@ macro_rules! assert_eq_complex { #[macro_export] /// assert if the matrix is U(2) ( unitary 2 x 2) +// TODO example macro_rules! assert_matrix_is_unitary_2 { ($m:expr, $epsilon:expr) => {{ use nalgebra::ComplexField; @@ -202,6 +205,7 @@ macro_rules! assert_matrix_is_unitary_2 { #[macro_export] /// assert if the matrix is U(3) (unitary 3 x 3) +// TODO example macro_rules! assert_matrix_is_unitary_3 { ($m:expr, $epsilon:expr) => {{ use nalgebra::ComplexField; @@ -222,6 +226,7 @@ macro_rules! assert_matrix_is_unitary_3 { #[macro_export] /// assert if the matrix is SU(2) (special unitary) +// TODO examples macro_rules! assert_matrix_is_su_2 { ($m:expr, $epsilon:expr) => {{ use nalgebra::ComplexField; @@ -242,6 +247,7 @@ macro_rules! assert_matrix_is_su_2 { #[macro_export] /// assert if the matrix is SU(3) (special unitary) +// TODO examples macro_rules! assert_matrix_is_su_3 { ($m:expr, $epsilon:expr) => {{ use nalgebra::ComplexField; diff --git a/src/number.rs b/src/number.rs index 573aafa5..9ab3d851 100644 --- a/src/number.rs +++ b/src/number.rs @@ -29,7 +29,7 @@ where } } -/// Fixe point number representewd by i32 for the integer part and 128 bits (16 bytes) as the decimal part +/// Fixe point number represented by i32 for the integer part and 128 bits (16 bytes) as the decimal part pub type I32U128 = FixedPointNumber; /* diff --git a/src/prelude.rs b/src/prelude.rs index 78deb403..43d1390b 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -12,7 +12,7 @@ pub use super::{ }, LatticeState, LatticeStateDefault, LatticeStateEFSyncDefault, LatticeStateNew, LatticeStateWithEField, LatticeStateWithEFieldNew, SimulationStateLeap, - SimulationStateLeapFrog, SimulationStateSynchrone, + SimulationStateLeapFrog, SimulationStateSynchronous, }, CMatrix3, Complex, ComplexField, Real, }; diff --git a/src/simulation/mod.rs b/src/simulation/mod.rs index bc1dfdad..ddffdaea 100644 --- a/src/simulation/mod.rs +++ b/src/simulation/mod.rs @@ -1,4 +1,6 @@ -//! Simulation module. Containe Monte Carlo algorithms and simulation states. +//! Simulation module. Contains Monte Carlo algorithms and simulation states. +//! +//! See submodule documentation [`monte_carlo`] and [`state`] for more details. // TODO more doc pub mod monte_carlo; diff --git a/src/simulation/monte_carlo/heat_bath.rs b/src/simulation/monte_carlo/heat_bath.rs index 5b8a9f29..cf9ba2c0 100644 --- a/src/simulation/monte_carlo/heat_bath.rs +++ b/src/simulation/monte_carlo/heat_bath.rs @@ -52,7 +52,7 @@ impl HeatBathSweep { Self { rng } } - /// Absorbe self and return the RNG as owned. It essentialy deconstruct the structure. + /// Absorbed self and return the RNG as owned. It essentially deconstruct the structure. pub fn rng_owned(self) -> Rng { self.rng } @@ -67,13 +67,13 @@ impl HeatBathSweep { &self.rng } - /// Apply te SU2 heat bath methode. + /// Apply te SU2 heat bath method. #[inline] fn heat_bath_su2(&mut self, staple: CMatrix2, beta: f64) -> CMatrix2 { - let staple_coeef = staple.determinant().real().sqrt(); - if staple_coeef.is_normal() { - let v_r: CMatrix2 = staple.adjoint() / Complex::from(staple_coeef); - let d_heat_bath_r = HeatBathDistribution::new(beta * staple_coeef).unwrap(); + let staple_coefficient = staple.determinant().real().sqrt(); + if staple_coefficient.is_normal() { + let v_r: CMatrix2 = staple.adjoint() / Complex::from(staple_coefficient); + let d_heat_bath_r = HeatBathDistribution::new(beta * staple_coefficient).unwrap(); let rand_m_r: CMatrix2 = self.rng.sample(d_heat_bath_r); rand_m_r * v_r } @@ -84,7 +84,7 @@ impl HeatBathSweep { } } - /// Apply the pesudo heat bath methode and return the new link. + /// Apply the pseudo heat bath methods and return the new link. #[inline] fn get_modif( &mut self, @@ -108,7 +108,7 @@ impl HeatBathSweep { } #[inline] - // TODO improve error handeling + // TODO improve error handling fn next_element_default( &mut self, mut state: LatticeStateDefault, diff --git a/src/simulation/monte_carlo/hybrid.rs b/src/simulation/monte_carlo/hybrid.rs index 7517d429..26e637ef 100644 --- a/src/simulation/monte_carlo/hybrid.rs +++ b/src/simulation/monte_carlo/hybrid.rs @@ -2,6 +2,8 @@ //! //! this module present different ways to combine multiple method +// TODO examples + use core::fmt::{Debug, Display}; use std::error::Error; use std::marker::PhantomData; @@ -12,12 +14,12 @@ use serde::{Deserialize, Serialize}; use super::{super::state::LatticeState, MonteCarlo}; -/// Error given by [`HybrideMethodeVec`] +/// Error given by [`HybridMethodVec`] #[non_exhaustive] #[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -pub enum HybrideMethodeVecError { - /// An Error comming from one of the method. +pub enum HybridMethodVecError { + /// An Error coming from one of the method. /// /// the first field usize gives the position of the method giving the error Error(usize, Error), @@ -25,18 +27,18 @@ pub enum HybrideMethodeVecError { NoMethod, } -impl Display for HybrideMethodeVecError { +impl Display for HybridMethodVecError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::NoMethod => write!(f, "no monte carlo method"), Self::Error(index, error) => { - write!(f, "error during intgration step {}: {}", index, error) + write!(f, "error during integration step {}: {}", index, error) } } } } -impl Error for HybrideMethodeVecError { +impl Error for HybridMethodVecError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { Self::NoMethod => None, @@ -45,9 +47,9 @@ impl Error for HybrideMethodeVecError { } } -/// Adaptator used to convert the error to another type. It is intented to use with [`HybrideMethodeVec`]. +/// Adaptor used to convert the error to another type. It is intended to use with [`HybridMethodVec`]. #[derive(PartialEq, Eq, Debug)] -pub struct AdaptatorMethodError<'a, MC, State, ErrorBase, Error, const D: usize> +pub struct AdaptorMethodError<'a, MC, State, ErrorBase, Error, const D: usize> where MC: MonteCarlo + ?Sized, ErrorBase: Into, @@ -58,7 +60,7 @@ where } impl<'a, MC, State, ErrorBase, Error, const D: usize> - AdaptatorMethodError<'a, MC, State, ErrorBase, Error, D> + AdaptorMethodError<'a, MC, State, ErrorBase, Error, D> where MC: MonteCarlo + ?Sized, ErrorBase: Into, @@ -72,19 +74,19 @@ where } } - /// Getter for the reference holded by self. + /// Getter for the reference hold by self. pub fn data_mut(&mut self) -> &mut MC { self.data } - /// Getter for the reference holded by self. + /// Getter for the reference hold by self. pub fn data(&self) -> &MC { self.data } } impl<'a, MC, State, ErrorBase, Error, const D: usize> AsMut - for AdaptatorMethodError<'a, MC, State, ErrorBase, Error, D> + for AdaptorMethodError<'a, MC, State, ErrorBase, Error, D> where MC: MonteCarlo + ?Sized, ErrorBase: Into, @@ -96,7 +98,7 @@ where } impl<'a, MC, State, ErrorBase, Error, const D: usize> AsRef - for AdaptatorMethodError<'a, MC, State, ErrorBase, Error, D> + for AdaptorMethodError<'a, MC, State, ErrorBase, Error, D> where MC: MonteCarlo + ?Sized, ErrorBase: Into, @@ -108,7 +110,7 @@ where } impl<'a, MC, State, ErrorBase, Error, const D: usize> MonteCarlo - for AdaptatorMethodError<'a, MC, State, ErrorBase, Error, D> + for AdaptorMethodError<'a, MC, State, ErrorBase, Error, D> where MC: MonteCarlo + ?Sized, ErrorBase: Into, @@ -122,17 +124,17 @@ where } } -/// hybride methode that combine multiple methodes. It requires that all methods return the same error. -/// You can use [`AdaptatorMethodError`] to convert the error. -/// If you want type with different error you can use [`HybrideMethodeCouple`]. -pub struct HybrideMethodeVec<'a, State, E, const D: usize> +/// hybrid method that combine multiple methods. It requires that all methods return the same error. +/// You can use [`AdaptorMethodError`] to convert the error. +/// If you want type with different error you can use [`HybridMethodCouple`]. +pub struct HybridMethodVec<'a, State, E, const D: usize> where State: LatticeState, { methods: Vec<&'a mut dyn MonteCarlo>, } -impl<'a, State, E, const D: usize> HybrideMethodeVec<'a, State, E, D> +impl<'a, State, E, const D: usize> HybridMethodVec<'a, State, E, D> where State: LatticeState, { @@ -145,7 +147,9 @@ where /// Create an empty Self. pub fn new_empty() -> Self { - Self { methods: vec![] } + Self { + methods: Vec::new(), + } } /// Create an empty Self where the vector is preallocated for `capacity` element. @@ -160,17 +164,17 @@ where Self { methods } } - /// Get a mutable reference to the methodes used, + /// Get a mutable reference to the methods used, pub fn methods_mut(&mut self) -> &mut Vec<&'a mut dyn MonteCarlo> { &mut self.methods } - /// Add a methode at the end. + /// Add a method at the end. pub fn push_method(&mut self, mc_ref: &'a mut dyn MonteCarlo) { self.methods.push(mc_ref); } - /// Remove a methode at the end an returns it. Return None if the methodes is empty. + /// Remove a method at the end an returns it. Return None if the methods is empty. pub fn pop_method(&mut self) -> Option<&'a mut dyn MonteCarlo> { self.methods.pop() } @@ -187,7 +191,7 @@ where } impl<'a, State, E, const D: usize> AsRef>> - for HybrideMethodeVec<'a, State, E, D> + for HybridMethodVec<'a, State, E, D> where State: LatticeState, { @@ -197,7 +201,7 @@ where } impl<'a, State, E, const D: usize> AsMut>> - for HybrideMethodeVec<'a, State, E, D> + for HybridMethodVec<'a, State, E, D> where State: LatticeState, { @@ -206,7 +210,7 @@ where } } -impl<'a, State, E, const D: usize> Default for HybrideMethodeVec<'a, State, E, D> +impl<'a, State, E, const D: usize> Default for HybridMethodVec<'a, State, E, D> where State: LatticeState, { @@ -215,49 +219,49 @@ where } } -impl<'a, State, E, const D: usize> MonteCarlo for HybrideMethodeVec<'a, State, E, D> +impl<'a, State, E, const D: usize> MonteCarlo for HybridMethodVec<'a, State, E, D> where State: LatticeState, { - type Error = HybrideMethodeVecError; + type Error = HybridMethodVecError; #[inline] fn next_element(&mut self, mut state: State) -> Result { if self.methods.is_empty() { - return Err(HybrideMethodeVecError::NoMethod); + return Err(HybridMethodVecError::NoMethod); } for (index, m) in &mut self.methods.iter_mut().enumerate() { let result = state.monte_carlo_step(*m); match result { Ok(new_state) => state = new_state, - Err(error) => return Err(HybrideMethodeVecError::Error(index, error)), + Err(error) => return Err(HybridMethodVecError::Error(index, error)), } } Ok(state) } } -/// Error given by [`HybrideMethodeCouple`] +/// Error given by [`HybridMethodCouple`] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -pub enum HybrideMethodeCoupleError { +pub enum HybridMethodCoupleError { /// First method gave an error ErrorFirst(Error1), /// Second method gave an error ErrorSecond(Error2), } -impl Display for HybrideMethodeCoupleError { +impl Display for HybridMethodCoupleError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::ErrorFirst(error) => write!(f, "error during intgration step 1: {}", error), - Self::ErrorSecond(error) => write!(f, "error during intgration step 2: {}", error), + Self::ErrorFirst(error) => write!(f, "error during integration step 1: {}", error), + Self::ErrorSecond(error) => write!(f, "error during integration step 2: {}", error), } } } impl Error - for HybrideMethodeCoupleError + for HybridMethodCoupleError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { @@ -271,7 +275,7 @@ impl Error /// Couples for a large number of methods. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -pub struct HybrideMethodeCouple +pub struct HybridMethodCouple where MC1: MonteCarlo, MC2: MonteCarlo, @@ -283,7 +287,7 @@ where } impl - HybrideMethodeCouple + HybridMethodCouple where MC1: MonteCarlo, MC2: MonteCarlo, @@ -319,42 +323,42 @@ where } impl MonteCarlo - for HybrideMethodeCouple + for HybridMethodCouple where MC1: MonteCarlo, MC2: MonteCarlo, State: LatticeState, { - type Error = HybrideMethodeCoupleError; + type Error = HybridMethodCoupleError; #[inline] fn next_element(&mut self, mut state: State) -> Result { state = state .monte_carlo_step(&mut self.method_1) - .map_err(HybrideMethodeCoupleError::ErrorFirst)?; + .map_err(HybridMethodCoupleError::ErrorFirst)?; state .monte_carlo_step(&mut self.method_2) - .map_err(HybrideMethodeCoupleError::ErrorSecond) + .map_err(HybridMethodCoupleError::ErrorSecond) } } /// Combine three methods. -pub type HybrideMethodeTriple = - HybrideMethodeCouple< - HybrideMethodeCouple, - HybrideMethodeCoupleError, +pub type HybridMethodTriple = + HybridMethodCouple< + HybridMethodCouple, + HybridMethodCoupleError, MC3, Error3, State, D, >; -/// Error returned by [`HybrideMethodeTriple`]. -pub type HybrideMethodeTripleError = - HybrideMethodeCoupleError, Error3>; +/// Error returned by [`HybridMethodTriple`]. +pub type HybridMethodTripleError = + HybridMethodCoupleError, Error3>; /// Combine four methods. -pub type HybrideMethodeQuadruple< +pub type HybridMethodQuadruple< MC1, Error1, MC2, @@ -365,21 +369,21 @@ pub type HybrideMethodeQuadruple< Error4, State, const D: usize, -> = HybrideMethodeCouple< - HybrideMethodeTriple, - HybrideMethodeTripleError, +> = HybridMethodCouple< + HybridMethodTriple, + HybridMethodTripleError, MC4, Error4, State, D, >; -/// Error returned by [`HybrideMethodeQuadruple`]. -pub type HybrideMethodeQuadrupleError = - HybrideMethodeCoupleError, Error4>; +/// Error returned by [`HybridMethodQuadruple`]. +pub type HybridMethodQuadrupleError = + HybridMethodCoupleError, Error4>; /// Combine four methods. -pub type HybrideMethodeQuintuple< +pub type HybridMethodQuintuple< MC1, Error1, MC2, @@ -392,15 +396,15 @@ pub type HybrideMethodeQuintuple< Error5, State, const D: usize, -> = HybrideMethodeCouple< - HybrideMethodeQuadruple, - HybrideMethodeQuadrupleError, +> = HybridMethodCouple< + HybridMethodQuadruple, + HybridMethodQuadrupleError, MC5, Error5, State, D, >; -/// Error returned by [`HybrideMethodeQuintuple`]. -pub type HybrideMethodeTripleQuintuple = - HybrideMethodeCoupleError, Error5>; +/// Error returned by [`HybridMethodQuintuple`]. +pub type HybridMethodQuintupleError = + HybridMethodCoupleError, Error5>; diff --git a/src/simulation/monte_carlo/hybrid_monte_carlo.rs b/src/simulation/monte_carlo/hybrid_monte_carlo.rs index c52a30a0..51328460 100644 --- a/src/simulation/monte_carlo/hybrid_monte_carlo.rs +++ b/src/simulation/monte_carlo/hybrid_monte_carlo.rs @@ -1,4 +1,4 @@ -//! Hybrid Monte Carlo methode +//! Hybrid Monte Carlo method //! //! # Example //! ``` @@ -41,7 +41,8 @@ use super::{ super::{ super::{error::MultiIntegrationError, integrator::SymplecticIntegrator, Real}, state::{ - LatticeState, LatticeStateEFSyncDefault, SimulationStateLeap, SimulationStateSynchrone, + LatticeState, LatticeStateEFSyncDefault, SimulationStateLeap, + SimulationStateSynchronous, }, }, MonteCarlo, MonteCarloDefault, @@ -50,17 +51,20 @@ use super::{ /// Hybrid Monte Carlo algorithm (HCM for short). /// /// The idea of HCM is to generate a random set on conjugate momenta to the link matrices. -/// This conjugatewd momenta is also refed as the "Electric" field +/// This conjugated momenta is also refed as the "Electric" field /// or `e_field` with distribution N(0, 1 / beta). And to solve the equation of motion. /// The new state is accepted with probability Exp( -H_old + H_new) where the Hamiltonian has an extra term Tr(E_i ^ 2). -/// The advantage is that the simulation can be done in a simpleptic way i.e. it conserved the Hamiltonian. -/// Which means that the methode has a high acceptance rate. +/// The advantage is that the simulation can be done in a symplectic way i.e. it conserved the Hamiltonian. +/// Which means that the method has a high acceptance rate. +/// +/// # Example +/// See the the level module documentation. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct HybridMonteCarlo where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -74,8 +78,8 @@ where impl HybridMonteCarlo where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -108,10 +112,10 @@ where pub internal.number_of_steps() -> usize ); - /// gvies the following parameter for the HCM : - /// - delta_t is the step size per intgration of the equation of motion + /// gives the following parameter for the HCM : + /// - delta_t is the step size per integration of the equation of motion /// - number_of_steps is the number of time - /// - integrator is the methode to solve the equation of motion + /// - integrator is the methods to solve the equation of motion /// - rng, a random number generator pub fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self { Self { @@ -124,7 +128,7 @@ where } } - /// Get a mutlable reference to the rng. + /// Get a mutable reference to the rng. pub fn rng_mut(&mut self) -> &mut Rng { &mut self.rng } @@ -137,8 +141,8 @@ where impl AsRef for HybridMonteCarlo where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -153,8 +157,8 @@ where impl AsMut for HybridMonteCarlo where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -169,8 +173,8 @@ where impl MonteCarlo for HybridMonteCarlo where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -194,19 +198,23 @@ where #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] struct HybridMonteCarloInternal where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { + /// integration step. delta_t: Real, + /// number of steps to do. number_of_steps: usize, + //// integrator used by the internal method integrator: I, + /// The phantom data such that State can be a generic parameter without being stored. #[cfg_attr(feature = "serde-serialize", serde(skip))] _phantom: PhantomData, } impl HybridMonteCarloInternal where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { getter!( @@ -247,7 +255,7 @@ where impl AsRef for HybridMonteCarloInternal where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { fn as_ref(&self) -> &I { @@ -257,7 +265,7 @@ where impl AsMut for HybridMonteCarloInternal where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { fn as_mut(&mut self) -> &mut I { @@ -267,7 +275,7 @@ where impl MonteCarloDefault for HybridMonteCarloInternal where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { type Error = MultiIntegrationError; @@ -294,17 +302,20 @@ where /// Hybrid Monte Carlo algorithm ( HCM for short) with diagnostics. /// /// The idea of HCM is to generate a random set on conjugate momenta to the link matrices. -/// This conjugatewd momenta is also refed as the "Electric" field +/// This conjugated momenta is also refed as the "Electric" field /// or `e_field` with distribution N(0, 1 / beta). And to solve the equation of motion. /// The new state is accepted with probability Exp( -H_old + H_new) where the Hamiltonian has an extra term Tr(E_i ^ 2). -/// The advantage is that the simulation can be done in a simpleptic way i.e. it conserved the Hamiltonian. -/// Which means that the methode has a high acceptance rate. +/// The advantage is that the simulation can be done in a symplectic way i.e. it conserved the Hamiltonian. +/// Which means that the method has a high acceptance rate. +/// +/// # Example +/// See the the level module documentation. #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct HybridMonteCarloDiagnostic where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -318,8 +329,8 @@ where impl HybridMonteCarloDiagnostic where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -366,10 +377,10 @@ where usize ); - /// gvies the following parameter for the HCM : - /// - delta_t is the step size per intgration of the equation of motion + /// gives the following parameter for the HCM : + /// - delta_t is the step size per integration of the equation of motion /// - number_of_steps is the number of time - /// - integrator is the methode to solve the equation of motion + /// - integrator is the method to solve the equation of motion /// - rng, a random number generator pub fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self { Self { @@ -382,7 +393,7 @@ where } } - /// Get a mutlable reference to the rng. + /// Get a mutable reference to the rng. pub fn rng_mut(&mut self) -> &mut Rng { &mut self.rng } @@ -405,8 +416,8 @@ where impl AsRef for HybridMonteCarloDiagnostic where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -421,8 +432,8 @@ where impl AsMut for HybridMonteCarloDiagnostic where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -438,8 +449,8 @@ where impl MonteCarlo for HybridMonteCarloDiagnostic where - State: LatticeState + Clone, - LatticeStateEFSyncDefault: SimulationStateSynchrone, + State: LatticeState + Clone + ?Sized, + LatticeStateEFSyncDefault: SimulationStateSynchronous, I: SymplecticIntegrator< LatticeStateEFSyncDefault, SimulationStateLeap, D>, @@ -463,7 +474,7 @@ where #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] struct HybridMonteCarloInternalDiagnostics where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { delta_t: Real, @@ -477,7 +488,7 @@ where impl HybridMonteCarloInternalDiagnostics where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { getter!( @@ -523,6 +534,7 @@ where self.has_replace_last } + /// get the integrator as a mutable reference. pub fn integrator_mut(&mut self) -> &mut I { &mut self.integrator } @@ -530,7 +542,7 @@ where impl AsRef for HybridMonteCarloInternalDiagnostics where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { fn as_ref(&self) -> &I { @@ -540,7 +552,7 @@ where impl AsMut for HybridMonteCarloInternalDiagnostics where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { fn as_mut(&mut self) -> &mut I { @@ -551,7 +563,7 @@ where impl MonteCarloDefault for HybridMonteCarloInternalDiagnostics where - State: SimulationStateSynchrone, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator, D>, { type Error = MultiIntegrationError; diff --git a/src/simulation/monte_carlo/metropolis_hastings.rs b/src/simulation/monte_carlo/metropolis_hastings.rs index c192e5d9..d2efae19 100644 --- a/src/simulation/monte_carlo/metropolis_hastings.rs +++ b/src/simulation/monte_carlo/metropolis_hastings.rs @@ -1,7 +1,45 @@ -//! Metropolis Hastings methode +//! Metropolis Hastings method //! -//! I recomand not using methode in this module, but they may have niche usage. -//! look at [`super::metropolis_hastings_sweep`] for a more common algoritm. +//! I recommend not using method in this module, but they may have niche usage. +//! look at [`super::metropolis_hastings_sweep`] for a more common algorithm. +//! +//! # Example +//! ```rust +//! use lattice_qcd_rs::{ +//! error::ImplementationError, +//! simulation::monte_carlo::MetropolisHastingsDeltaDiagnostic, +//! simulation::state::{LatticeState, LatticeStateDefault}, +//! ComplexField, +//! }; +//! +//! # use std::error::Error; +//! # fn main() -> Result<(), Box> { +//! let mut rng = rand::thread_rng(); +//! +//! let size = 1_000_f64; +//! let number_of_pts = 4; +//! let beta = 2_f64; +//! let mut simulation = +//! LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?; +//! +//! let spread_parameter = 1E-5_f64; +//! let mut mc = MetropolisHastingsDeltaDiagnostic::new(spread_parameter, rng) +//! .ok_or(ImplementationError::OptionWithUnexpectedNone)?; +//! +//! let number_of_sims = 100; +//! for _ in 0..number_of_sims / 10 { +//! for _ in 0..10 { +//! simulation = simulation.monte_carlo_step(&mut mc)?; +//! } +//! simulation.normalize_link_matrices(); // we renormalize all matrices back to SU(3); +//! } +//! let average = simulation +//! .average_trace_plaquette() +//! .ok_or(ImplementationError::OptionWithUnexpectedNone)? +//! .real(); +//! # Ok(()) +//! # } +//! ``` use rand_distr::Distribution; #[cfg(feature = "serde-serialize")] @@ -13,8 +51,8 @@ use super::{ error::Never, field::LinkMatrix, lattice::{ - Direction, LatticeCyclique, LatticeElementToIndex, LatticeLink, - LatticeLinkCanonical, LatticePoint, + Direction, LatticeCyclic, LatticeElementToIndex, LatticeLink, LatticeLinkCanonical, + LatticePoint, }, su3, Complex, Real, }, @@ -23,14 +61,20 @@ use super::{ delta_s_old_new_cmp, MonteCarlo, MonteCarloDefault, }; -/// Metropolis Hastings algorithm. Very slow, use [`MetropolisHastingsDeltaDiagnostic`] instead when applicable. +/// Metropolis Hastings algorithm. Very slow, use [`MetropolisHastingsDeltaDiagnostic`] +/// instead when applicable. /// -/// This a very general method that can manage every [`LatticeState`] but the tread off is that it is much slower than -/// a dedicated algorithm knowing the from of the hamiltonian. If you want to use your own hamiltonian I advice to implemnt +/// This a very general method that can manage every [`LatticeState`] but the tread off +/// is that it is much slower than +/// a dedicated algorithm knowing the from of the hamiltonian. If you want to use your own +/// hamiltonian I advice to implement /// you own method too. /// -/// Note that this methode does not do a sweep but change random link matrix, +/// Note that this method does not do a sweep but change random link matrix, /// for a sweep there is [`super::MetropolisHastingsSweep`]. +/// +/// # Example +/// See the example of [`super::McWrapper`] #[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct MetropolisHastings { @@ -43,7 +87,7 @@ impl MetropolisHastings { /// than 0. `0.1_f64` is a good choice for this parameter. /// /// `number_of_update` is the number of times a link matrix is randomly changed. - /// `spread` is the spead factor for the random matrix change + /// `spread` is the spread factor for the random matrix change /// ( used in [`su3::random_su3_close_to_unity`]). pub fn new(number_of_update: usize, spread: Real) -> Option { if number_of_update == 0 || !(spread > 0_f64 && spread < 1_f64) { @@ -56,7 +100,7 @@ impl MetropolisHastings { } getter_copy!( - /// Get the number of atempted updates per steps. + /// Get the number of attempted updates per steps. pub const number_of_update() -> usize ); @@ -113,9 +157,9 @@ where /// Metropolis Hastings algorithm with diagnostics. Very slow, use [`MetropolisHastingsDeltaDiagnostic`] instead. /// -/// Similar to [`MetropolisHastingsDiagnostic`] but with diagnotic information. +/// Similar to [`MetropolisHastingsDiagnostic`] but with diagnostic information. /// -/// Note that this methode does not do a sweep but change random link matrix, +/// Note that this method does not do a sweep but change random link matrix, /// for a sweep there is [`super::MetropolisHastingsSweep`]. /// /// # Example @@ -134,7 +178,7 @@ impl MetropolisHastingsDiagnostic { /// than 0. `0.1_f64` is a good choice for this parameter. /// /// `number_of_update` is the number of times a link matrix is randomly changed. - /// `spread` is the spead factor for the random matrix change + /// `spread` is the spread factor for the random matrix change /// ( used in [`su3::random_su3_close_to_unity`]). pub fn new(number_of_update: usize, spread: Real) -> Option { if number_of_update == 0 || spread <= 0_f64 || spread >= 1_f64 { @@ -242,8 +286,11 @@ where /// Metropolis Hastings algorithm with diagnostics. /// -/// Note that this methode does not do a sweep but change random link matrix, +/// Note that this method does not do a sweep but change random link matrix, /// for a sweep there is [`super::MetropolisHastingsSweep`]. +/// +/// # Example +/// see example of [`super`] #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct MetropolisHastingsDeltaDiagnostic { @@ -289,7 +336,7 @@ impl MetropolisHastingsDeltaDiagnostic { /// than 0. /// /// `number_of_update` is the number of times a link matrix is randomly changed. - /// `spread` is the spead factor for the random matrix change + /// `spread` is the spread factor for the random matrix change /// ( used in [`su3::random_su3_close_to_unity`]). pub fn new(spread: Real, rng: Rng) -> Option { if spread <= 0_f64 || spread >= 1_f64 { @@ -303,7 +350,7 @@ impl MetropolisHastingsDeltaDiagnostic { }) } - /// Absorbe self and return the RNG as owned. It essentialy deconstruct the structure. + /// Absorbs self and return the RNG as owned. It essentially deconstruct the structure. pub fn rng_owned(self) -> Rng { self.rng } @@ -311,7 +358,7 @@ impl MetropolisHastingsDeltaDiagnostic { #[inline] fn delta_s( link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, link: &LatticeLinkCanonical, new_link: &na::Matrix3, beta: Real, @@ -328,7 +375,7 @@ impl MetropolisHastingsDeltaDiagnostic { state: &LatticeStateDefault, ) -> (LatticeLinkCanonical, na::Matrix3) { let d_p = rand::distributions::Uniform::new(0, state.lattice().dim()); - let d_d = rand::distributions::Uniform::new(0, LatticeCyclique::::dim_st()); + let d_d = rand::distributions::Uniform::new(0, LatticeCyclic::::dim_st()); let point = LatticePoint::from_fn(|_| d_p.sample(&mut self.rng)); let direction = Direction::positive_directions()[d_d.sample(&mut self.rng)]; @@ -436,8 +483,7 @@ mod test { let number_of_pts = 4; let beta = 2_f64; let mut simulation = - LatticeStateDefault::<4>::new_deterministe(size, beta, number_of_pts, &mut rng) - .unwrap(); + LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng).unwrap(); let mut mcd = MetropolisHastingsDeltaDiagnostic::new(0.01_f64, rng).unwrap(); for _ in 0_u32..10_u32 { diff --git a/src/simulation/monte_carlo/metropolis_hastings_sweep.rs b/src/simulation/monte_carlo/metropolis_hastings_sweep.rs index 5fe5129d..0c8af6f6 100644 --- a/src/simulation/monte_carlo/metropolis_hastings_sweep.rs +++ b/src/simulation/monte_carlo/metropolis_hastings_sweep.rs @@ -1,4 +1,4 @@ -//! Metropolis Hastings methode +//! Metropolis Hastings method //! //! # Example //! see [`MetropolisHastingsSweep`] @@ -12,7 +12,7 @@ use super::{ super::{ error::Never, field::LinkMatrix, - lattice::{LatticeCyclique, LatticeElementToIndex, LatticeLink, LatticeLinkCanonical}, + lattice::{LatticeCyclic, LatticeElementToIndex, LatticeLink, LatticeLinkCanonical}, su3, Complex, Real, }, state::{LatticeState, LatticeStateDefault}, @@ -20,7 +20,7 @@ use super::{ delta_s_old_new_cmp, MonteCarlo, }; -/// Metropolis Hastings methode by doing a pass on all points +/// Metropolis Hastings method by doing a pass on all points /// /// # Example /// ``` @@ -72,7 +72,7 @@ impl MetropolisHastingsSweep { /// than 0. /// /// `number_of_update` is the number of times a link matrix is randomly changed. - /// `spread` is the spead factor for the random matrix change + /// `spread` is the spread factor for the random matrix change /// ( used in [`su3::random_su3_close_to_unity`]). pub fn new(number_of_update: usize, spread: Real, rng: Rng) -> Option { if number_of_update == 0 || spread <= 0_f64 || spread >= 1_f64 { @@ -92,7 +92,7 @@ impl MetropolisHastingsSweep { self.prob_replace_mean } - /// Number of accepted chnage during last sweep + /// Number of accepted change during last sweep pub fn number_replace_last(&self) -> usize { self.number_replace_last } @@ -110,7 +110,7 @@ impl MetropolisHastingsSweep { #[inline] fn delta_s( link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, link: &LatticeLinkCanonical, new_link: &na::Matrix3, beta: Real, diff --git a/src/simulation/monte_carlo/mod.rs b/src/simulation/monte_carlo/mod.rs index 3f58ae04..3cadb423 100644 --- a/src/simulation/monte_carlo/mod.rs +++ b/src/simulation/monte_carlo/mod.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use super::state::{LatticeState, LatticeStateDefault}; use crate::{ field::LinkMatrix, - lattice::{Direction, LatticeCyclique, LatticeLink, LatticeLinkCanonical}, + lattice::{Direction, LatticeCyclic, LatticeLink, LatticeLinkCanonical}, Complex, Real, }; @@ -66,7 +66,7 @@ pub trait MonteCarlo where State: LatticeState, { - /// Error returned while getting the next ellement. + /// Error returned while getting the next element. type Error; /// Do one Monte Carlo simulation step. @@ -76,7 +76,7 @@ where fn next_element(&mut self, state: State) -> Result; } -/// Some times it is esayer to just implement a potential next element, the rest is done automatically using an [`McWrapper`]. +/// Some times it is easier to just implement a potential next element, the rest is done automatically using an [`McWrapper`]. /// /// To get an [`MonteCarlo`] use the wrapper [`McWrapper`]. /// # Example @@ -110,6 +110,7 @@ where /// } /// // operation at the end of the simulation /// let (_, rng) = wrapper.deconstruct(); // get the rng back +/// // continue with further operation using the same rng ... /// # Ok(()) /// # } /// ``` @@ -117,13 +118,13 @@ pub trait MonteCarloDefault where State: LatticeState, { - /// Error returned while getting the next ellement. + /// Error returned while getting the next element. type Error; /// Generate a radom element from the previous element (like a Markov chain). /// /// # Errors - /// Gives an error if a potential next ellement cannot be generated. + /// Gives an error if a potential next element cannot be generated. fn potential_next_element( &mut self, state: &State, @@ -145,7 +146,7 @@ where /// Get the next element in the chain either the old state or a new one replacing it. /// /// # Errors - /// Gives an error if a potential next ellement cannot be generated. + /// Gives an error if a potential next element cannot be generated. fn next_element_default( &mut self, state: State, @@ -321,7 +322,7 @@ where #[inline] fn delta_s_old_new_cmp( link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, link: &LatticeLinkCanonical, new_link: &na::Matrix3, beta: Real, @@ -336,7 +337,7 @@ fn delta_s_old_new_cmp( #[inline] fn staple( link_matrix: &LinkMatrix, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, link: &LatticeLinkCanonical, ) -> na::Matrix3 { let dir_j = link.dir(); diff --git a/src/simulation/monte_carlo/overrelaxation.rs b/src/simulation/monte_carlo/overrelaxation.rs index 04e43617..64fb110c 100644 --- a/src/simulation/monte_carlo/overrelaxation.rs +++ b/src/simulation/monte_carlo/overrelaxation.rs @@ -1,11 +1,11 @@ -//! Overrelaxation methode +//! Overrelaxation method //! //! The goal of the overrelaxation is to move thought the phase space as much as possible but conserving the hamiltonian. //! It can be used to improve the speed of thermalisation by vising more states. -//! Alone it can't advance the simulation as it preserved the hamiltonian. You need to use other methode with this one. -//! You can look at [`super::HybrideMethodeVec`] and [`super::HybrideMethodeCouple`]. +//! Alone it can't advance the simulation as it preserved the hamiltonian. You need to use other method with this one. +//! You can look at [`super::HybridMethodVec`] and [`super::HybridMethodCouple`]. //! -//! In my limimited experience [`OverrelaxationSweepReverse`] moves a bit more though the phase space than [`OverrelaxationSweepRotation`]. +//! In my limited experience [`OverrelaxationSweepReverse`] moves a bit more though the phase space than [`OverrelaxationSweepRotation`]. //! The difference is slight though. //! //! # Example @@ -42,13 +42,13 @@ use super::{ staple, MonteCarlo, }; -/// Overrelaxation algortihm using rotation methode. +/// Overrelaxation algorithm using rotation method. /// /// Alone it can't advance the simulation as it preserved the hamiltonian. -/// You need to use other methode with this one. -/// You can look at [`super::HybrideMethodeVec`] and [`super::HybrideMethodeCouple`]. +/// You need to use other method with this one. +/// You can look at [`super::HybridMethodVec`] and [`super::HybridMethodCouple`]. /// -/// The algorrtihm is described in section 2.1 up to step 2 using `\hat X_{NN}`. +/// The algorithm is described in section 2.1 up to step 2 using `\hat X_{NN}`. /// /// # Example /// ``` @@ -134,13 +134,13 @@ impl MonteCarlo, D> for OverrelaxationSwe } } -/// Overrelaxation algortihm using the reverse methode. +/// Overrelaxation algorithm using the reverse method. /// /// Alone it can't advance the simulation as it preserved the hamiltonian. -/// You need to use other methode with this one. -/// You can look at [`super::HybrideMethodeVec`] and [`super::HybrideMethodeCouple`]. +/// You need to use other method with this one. +/// You can look at [`super::HybridMethodVec`] and [`super::HybridMethodCouple`]. /// -/// The algorrtihm is described in . +/// The algorithm is described in . /// /// # Example /// see level module documentation [`super::overrelaxation`] @@ -222,7 +222,7 @@ mod test { MC: MonteCarlo, 3>, MC::Error: core::fmt::Debug, { - let state = LatticeStateDefault::<3>::new_deterministe(1_f64, 1_f64, 4, rng).unwrap(); + let state = LatticeStateDefault::<3>::new_determinist(1_f64, 1_f64, 4, rng).unwrap(); let h = state.hamiltonian_links(); let state2 = mc.next_element(state).unwrap(); let h2 = state2.hamiltonian_links(); diff --git a/src/simulation/state.rs b/src/simulation/state.rs index 43684e87..ceb17dc3 100644 --- a/src/simulation/state.rs +++ b/src/simulation/state.rs @@ -1,4 +1,8 @@ -//! Module containing the simulation State +//! Module containing the simulation State. +//! +//! See item documentation for more details. + +// TODO more doc use crossbeam::thread; use na::{ComplexField, SVector}; @@ -16,7 +20,7 @@ use super::{ field::{EField, LinkMatrix, Su3Adjoint}, integrator::SymplecticIntegrator, lattice::{ - Direction, DirectionList, LatticeCyclique, LatticeElementToIndex, LatticeLink, + Direction, DirectionList, LatticeCyclic, LatticeElementToIndex, LatticeLink, LatticeLinkCanonical, LatticePoint, }, su3, @@ -30,9 +34,10 @@ use super::{ pub type LeapFrogStateDefault = SimulationStateLeap, D>, D>; -/// trait to represent a pure gauge lattice state of dimention `D`. +/// Trait to represent a pure gauge lattice state of dimension `D`. /// /// It defines only one field: `link_matrix` of type [`LinkMatrix`]. +// TODO example pub trait LatticeState { /// Get the link matrices of this state. /// @@ -59,26 +64,30 @@ pub trait LatticeState { /// Replace the links matrices with the given input. It should panic if link matrix is not of /// the correct size. + /// /// # Panic /// Panic if the length of link_matrix is different from `lattice.get_number_of_canonical_links_space()` fn set_link_matrix(&mut self, link_matrix: LinkMatrix); - /// get the lattice into which the state exists - fn lattice(&self) -> &LatticeCyclique; + /// Get the lattice into which the state exists. + fn lattice(&self) -> &LatticeCyclic; - /// return the beta parameter of the states + /// Returns the beta parameter of the states. fn beta(&self) -> Real; /// C_A constant of the model, usually it is 3. const CA: Real; - /// return the Hamiltonian of the links configuration + /// Returns the Hamiltonian of the links configuration. fn hamiltonian_links(&self) -> Real; /// Do one monte carlo step with the given method. /// /// # Errors /// The error form `MonteCarlo::get_next_element` is propagated. + /// + /// # Example + // TODO Example fn monte_carlo_step(self, m: &mut M) -> Result where Self: Sized, @@ -87,20 +96,21 @@ pub trait LatticeState { m.next_element(self) } - /// Take the average of the trace of all plaquettes + /// Take the average of the trace of all plaquettes. + /// + /// # Example + // TODO Example fn average_trace_plaquette(&self) -> Option { self.link_matrix().average_trace_plaquette(self.lattice()) } } -/// trait for a way to create a [`LatticeState`] from some parameters. +/// Trait for a way to create a [`LatticeState`] from some parameters. /// /// It is separated from the [`LatticeState`] because not all [`LatticeState`] can be create in this way. /// By instance when there is also a field of conjugate momenta of the link matrices. -pub trait LatticeStateNew -where - Self: LatticeState + Sized, -{ +// TODO explain why !!! +pub trait LatticeStateNew: LatticeState + Sized { /// Error type type Error; @@ -109,8 +119,9 @@ where /// # Errors /// Give an error if the parameter are incorrect or the length of `link_matrix` does not correspond /// to `lattice`. + // TODO example fn new( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, link_matrix: LinkMatrix, ) -> Result; @@ -122,26 +133,25 @@ where /// [`LatticeStateEFSyncDefault`]. /// /// If you want to solve the equation of motion using an [`SymplecticIntegrator`] also implement -/// [`SimulationStateSynchrone`] and the wrapper [`SimulationStateLeap`] can give you an [`SimulationStateLeapFrog`]. +/// [`SimulationStateSynchronous`] and the wrapper [`SimulationStateLeap`] can give you an [`SimulationStateLeapFrog`]. /// /// It is used for the [`super::monte_carlo::HybridMonteCarlo`] algorithm. -pub trait LatticeStateWithEField -where - Self: LatticeState, -{ +// TODO explain why !!! example +pub trait LatticeStateWithEField: LatticeState { /// Reset the e_field with radom value distributed as N(0, 1 / beta) [`rand_distr::StandardNormal`]. /// # Errors - /// Gives and error if N(0, 0.5/beta ) is not a valide distribution (for exampple beta = 0) + /// Gives and error if N(0, 0.5/beta ) is not a valid distribution (for example beta = 0) + // TODO explain why !!! fn reset_e_field(&mut self, rng: &mut Rng) -> Result<(), StateInitializationError> where Rng: rand::Rng + ?Sized, { let d = rand_distr::Normal::new(0_f64, 0.5_f64 / self.beta())?; - let new_e_field = EField::new_deterministe(self.lattice(), rng, &d); - if !self.lattice().has_compatible_lenght_e_field(&new_e_field) { + let new_e_field = EField::new_determinist(self.lattice(), rng, &d); + if !self.lattice().has_compatible_length_e_field(&new_e_field) { return Err(StateInitializationError::IncompatibleSize); } - // TODO error handeling + // TODO error handling self.set_e_field( new_e_field .project_to_gauss(self.link_matrix(), self.lattice()) @@ -155,6 +165,7 @@ where /// Replace the electrical field with the given input. It should panic if the input is not of /// the correct size. + /// /// # Panic /// Panic if the length of link_matrix is different from `lattice.get_number_of_points()` fn set_e_field(&mut self, e_field: EField); @@ -162,20 +173,24 @@ where /// return the time state, i.e. the number of time the simulation ran. fn t(&self) -> usize; - /// get the derivative \partial_t U(link) + /// Get the derivative \partial_t U(link), returns [`None`] if the link is outside of the lattice. + /// + /// It is used in order to apply the equation of motion. fn derivative_u( link: &LatticeLinkCanonical, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option; - /// get the derivative \partial_t E(point) + /// Get the derivative \partial_t E(point), returns [`None`] if the link is outside of the lattice. + /// + /// It is used in order to apply the equation of motion. fn derivative_e( point: &LatticePoint, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option>; /// Get the energy of the conjugate momenta configuration @@ -188,7 +203,8 @@ where } } -/// Trait to create a simulation state +/// Trait to create a simulation state. +// TODO why, example pub trait LatticeStateWithEFieldNew where Self: LatticeStateWithEField + Sized, @@ -202,19 +218,20 @@ where /// Give an error if the parameter are incorrect or the length of `link_matrix` /// and `e_field` does not correspond to `lattice` fn new( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, e_field: EField, link_matrix: LinkMatrix, t: usize, ) -> Result; - /// Create a new state with e_field randomly distributed as [`rand_distr::Normal`] + /// Create a new state with e_field randomly distributed as [`rand_distr::Normal`]^. + /// /// # Errors - /// Gives an error if N(0, 0.5/beta ) is not a valide distribution (for exampple beta = 0) + /// Gives an error if N(0, 0.5/beta ) is not a valid distribution (for example beta = 0) /// or propagate the error from [`LatticeStateWithEFieldNew::new`] fn new_random_e( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, link_matrix: LinkMatrix, rng: &mut R, @@ -224,7 +241,7 @@ where { // TODO verify let d = rand_distr::Normal::new(0_f64, 0.5_f64 / beta)?; - let e_field = EField::new_deterministe(&lattice, rng, &d) + let e_field = EField::new_determinist(&lattice, rng, &d) .project_to_gauss(&link_matrix, &lattice) .expect("Projection to gauss failed"); Self::new(lattice, beta, e_field, link_matrix, 0) @@ -239,11 +256,11 @@ where /// simulation look at /// [`LatticeStateEFSyncDefault`]. /// -/// I would adivce of implementing this trait and not [`SimulationStateLeapFrog`], as there is +/// I would advice of implementing this trait and not [`SimulationStateLeapFrog`], as there is /// a wrapper ([`SimulationStateLeap`]) for [`SimulationStateLeapFrog`]. /// Also not implementing both trait gives you a compile time verification that you did not /// considered a leap frog state as a sync one. -pub trait SimulationStateSynchrone +pub trait SimulationStateSynchronous where Self: LatticeStateWithEField + Clone, { @@ -251,6 +268,8 @@ where /// /// # Errors /// Return an error if the integration could not be done. + /// # Example + /// see [`SimulationStateLeapFrog::simulate_leap`] fn simulate_to_leapfrog( &self, integrator: &I, @@ -264,11 +283,12 @@ where } /// Does `number_of_steps` with `delta_t` at each step using a leap_frog algorithm by fist - /// doing half a setp and then finishing by doing half step. + /// doing half a step and then finishing by doing half step. /// /// # Errors /// Return an error if the integration could not be done /// or [`MultiIntegrationError::ZeroIntegration`] is the number of step is zero. + // TODO example fn simulate_using_leapfrog_n( &self, integrator: &I, @@ -303,16 +323,17 @@ where } } let state_sync = state_leap - .simulate_to_synchrone(integrator, delta_t) + .simulate_to_synchronous(integrator, delta_t) .map_err(|error| MultiIntegrationError::IntegrationError(number_of_steps, error))?; Ok(state_sync) } - /// Does the same thing as [`SimulationStateSynchrone::simulate_using_leapfrog_n`] + /// Does the same thing as [`SimulationStateSynchronous::simulate_using_leapfrog_n`] /// but use the default wrapper [`SimulationStateLeap`] for the leap frog state. /// /// # Errors /// Return an error if the integration could not be done. + // TODO example fn simulate_using_leapfrog_n_auto( &self, integrator: &I, @@ -329,6 +350,7 @@ where /// /// # Errors /// Return an error if the integration could not be done. + // TODO example fn simulate_sync(&self, integrator: &I, delta_t: Real) -> Result where I: SymplecticIntegrator + ?Sized, @@ -342,6 +364,7 @@ where /// # Errors /// Return an error if the integration could not be done /// or [`MultiIntegrationError::ZeroIntegration`] is the number of step is zero. + // TODO example fn simulate_sync_n( &self, integrator: &I, @@ -370,6 +393,37 @@ where /// /// # Errors /// Return an error if the integration could not be done + /// + /// # Example + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use lattice_qcd_rs::integrator::{SymplecticEulerRayon, SymplecticIntegrator}; + /// use lattice_qcd_rs::simulation::{ + /// LatticeStateDefault, LatticeStateEFSyncDefault, LatticeStateWithEField, + /// SimulationStateSynchronous, + /// }; + /// use rand::SeedableRng; + /// + /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed + /// let mut state = LatticeStateEFSyncDefault::new_random_e_state( + /// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, + /// &mut rng, + /// ); + /// let h = state.hamiltonian_total(); + /// + /// let integrator = SymplecticEulerRayon::default(); + /// for _ in 0..1 { + /// // Realistically you would want more steps + /// state = state.simulate_symplectic(&integrator, 0.000_001_f64)?; + /// } + /// let h2 = state.hamiltonian_total(); + /// + /// println!("The error on the Hamiltonian is {}", h - h2); + /// # Ok(()) + /// # } + /// ``` fn simulate_symplectic(&self, integrator: &I, delta_t: Real) -> Result where I: SymplecticIntegrator + ?Sized, @@ -383,6 +437,7 @@ where /// # Errors /// Return an error if the integration could not be done /// or [`MultiIntegrationError::ZeroIntegration`] is the number of step is zero. + // TODO example fn simulate_symplectic_n( &self, integrator: &I, @@ -407,11 +462,12 @@ where Ok(state) } - /// Does the same thing as [`SimulationStateSynchrone::simulate_symplectic_n`] + /// Does the same thing as [`SimulationStateSynchronous::simulate_symplectic_n`] /// but use the default wrapper [`SimulationStateLeap`] for the leap frog state. /// /// # Errors /// Return an error if the integration could not be done. + // TODO example fn simulate_symplectic_n_auto( &self, integrator: &I, @@ -428,23 +484,26 @@ where /// [`LatticeStateWithEField`] who represent link matrices at time T and its conjugate /// momenta at time T + 1/2. /// -/// If you have a [`SimulationStateSynchrone`] look at the wrapper [`SimulationStateLeap`]. +/// If you have a [`SimulationStateSynchronous`] look at the wrapper [`SimulationStateLeap`]. pub trait SimulationStateLeapFrog where Self: LatticeStateWithEField, { - /// Simulate the state to synchrone by finishing the half setp. + /// Simulate the state to synchronous by finishing the half step. /// /// # Errors /// Return an error if the integration could not be done. - fn simulate_to_synchrone( + /// + /// # Example + /// see [`SimulationStateLeapFrog::simulate_leap`] + fn simulate_to_synchronous( &self, integrator: &I, delta_t: Real, ) -> Result where Self: Sized, - State: SimulationStateSynchrone + ?Sized, + State: SimulationStateSynchronous + ?Sized, I: SymplecticIntegrator + ?Sized, { integrator.integrate_leap_sync(self, delta_t) @@ -454,11 +513,43 @@ where /// /// # Errors /// Return an error if the integration could not be done. + /// + /// # Example + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use lattice_qcd_rs::integrator::{SymplecticEulerRayon, SymplecticIntegrator}; + /// use lattice_qcd_rs::simulation::{ + /// LatticeStateDefault, LatticeStateEFSyncDefault, LatticeStateWithEField, SimulationStateSynchronous, SimulationStateLeapFrog, + /// }; + /// use rand::SeedableRng; + /// + /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed + /// let state = LatticeStateEFSyncDefault::new_random_e_state( + /// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, + /// &mut rng, + /// ); + /// let h = state.hamiltonian_total(); + /// let integrator = SymplecticEulerRayon::default(); + /// let mut leap_frog = state.simulate_to_leapfrog(&integrator,0.000_001_f64)?; + /// drop(state); + /// for _ in 0..2 { + /// // Realistically you would want more steps + /// leap_frog = leap_frog.simulate_leap(&integrator, 0.000_001_f64)?; + /// } + /// let state = leap_frog.simulate_to_synchronous(&integrator, 0.000_001_f64)?; + /// let h2 = state.hamiltonian_total(); + /// + /// println!("The error on the Hamiltonian is {}", h - h2); + /// # Ok(()) + /// # } + /// ``` fn simulate_leap(&self, integrator: &I, delta_t: Real) -> Result where Self: Sized, I: SymplecticIntegrator + ?Sized, - T: SimulationStateSynchrone + ?Sized, + T: SimulationStateSynchronous + ?Sized, { integrator.integrate_leap_leap(self, delta_t) } @@ -468,6 +559,39 @@ where /// # Errors /// Return an error if the integration could not be done /// or [`MultiIntegrationError::ZeroIntegration`] is the number of step is zero. + /// + /// # Example + /// /// # Example + /// ``` + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// use lattice_qcd_rs::integrator::{SymplecticEulerRayon, SymplecticIntegrator}; + /// use lattice_qcd_rs::simulation::{ + /// LatticeStateDefault, LatticeStateEFSyncDefault, LatticeStateWithEField, SimulationStateSynchronous, SimulationStateLeapFrog, + /// }; + /// use rand::SeedableRng; + /// + /// let mut rng = rand::rngs::StdRng::seed_from_u64(0); // change with your seed + /// let state = LatticeStateEFSyncDefault::new_random_e_state( + /// LatticeStateDefault::<3>::new_determinist(1_f64, 2_f64, 4, &mut rng)?, + /// &mut rng, + /// ); + /// let h = state.hamiltonian_total(); + /// let integrator = SymplecticEulerRayon::default(); + /// let mut leap_frog = state.simulate_to_leapfrog(&integrator,0.000_001_f64)?; + /// drop(state); + /// + /// // Realistically you would want more steps + /// leap_frog = leap_frog.simulate_leap_n(&integrator, 0.000_001_f64, 10)?; + /// + /// let state = leap_frog.simulate_to_synchronous(&integrator, 0.000_001_f64)?; + /// let h2 = state.hamiltonian_total(); + /// + /// println!("The error on the Hamiltonian is {}", h - h2); + /// # Ok(()) + /// # } + /// ``` fn simulate_leap_n( &self, integrator: &I, @@ -477,7 +601,7 @@ where where Self: Sized, I: SymplecticIntegrator + ?Sized, - T: SimulationStateSynchrone + ?Sized, + T: SimulationStateSynchronous + ?Sized, { if numbers_of_times == 0 { return Err(MultiIntegrationError::ZeroIntegration); @@ -500,7 +624,7 @@ where #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct LatticeStateDefault { - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, link_matrix: LinkMatrix, } @@ -508,62 +632,62 @@ pub struct LatticeStateDefault { impl LatticeStateDefault { /// Create a cold configuration. i.e. all the links are set to the unit matrix. /// - /// With the lattice of size `size` and dimension `number_of_points` ( see [`LatticeCyclique::new`] ) + /// With the lattice of size `size` and dimension `number_of_points` ( see [`LatticeCyclic::new`] ) /// and beta parameter `beta`. /// /// # Errors - /// Returns [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. + /// Returns [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid + /// for [`LatticeCyclic`]. /// Or propagate the error form [`Self::new`]. pub fn new_cold( size: Real, beta: Real, number_of_points: usize, ) -> Result { - let lattice = LatticeCyclique::new(size, number_of_points)?; + let lattice = LatticeCyclic::new(size, number_of_points)?; let link_matrix = LinkMatrix::new_cold(&lattice); Self::new(lattice, beta, link_matrix) } /// Create a "hot" configuration, i.e. the link matrices are chosen randomly. /// - /// With the lattice of size `size` and dimension `number_of_points` ( see [`LatticeCyclique::new`] ) + /// With the lattice of size `size` and dimension `number_of_points` ( see [`LatticeCyclic::new`] ) /// and beta parameter `beta`. /// - /// The creation is determiste in the sence that it is reproducible: + /// The creation is determinists meaning that it is reproducible: /// /// # Errors - /// Returns [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. + /// Returns [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid for [`LatticeCyclic`]. /// Or propagate the error form [`Self::new`]. /// /// # Example /// This example demonstrate how to reproduce the same configuration /// ``` - /// # use lattice_qcd_rs::{simulation::LatticeStateDefault, lattice::LatticeCyclique, dim}; + /// # use lattice_qcd_rs::{simulation::LatticeStateDefault, lattice::LatticeCyclic, dim}; /// use rand::{rngs::StdRng, SeedableRng}; /// /// let mut rng_1 = StdRng::seed_from_u64(0); /// let mut rng_2 = StdRng::seed_from_u64(0); /// // They have the same seed and should generate the same numbers /// assert_eq!( - /// LatticeStateDefault::<4>::new_deterministe(1_f64, 1_f64, 4, &mut rng_1).unwrap(), - /// LatticeStateDefault::<4>::new_deterministe(1_f64, 1_f64, 4, &mut rng_2).unwrap() + /// LatticeStateDefault::<4>::new_determinist(1_f64, 1_f64, 4, &mut rng_1).unwrap(), + /// LatticeStateDefault::<4>::new_determinist(1_f64, 1_f64, 4, &mut rng_2).unwrap() /// ); /// ``` - pub fn new_deterministe( + pub fn new_determinist( size: Real, beta: Real, number_of_points: usize, rng: &mut impl rand::Rng, ) -> Result { - let lattice = LatticeCyclique::new(size, number_of_points)?; - let link_matrix = LinkMatrix::new_deterministe(&lattice, rng); + let lattice = LatticeCyclic::new(size, number_of_points)?; + let link_matrix = LinkMatrix::new_determinist(&lattice, rng); Self::new(lattice, beta, link_matrix) } /// Correct the numerical drift, reprojecting all the link matrices to SU(3). /// see [`LinkMatrix::normalize`]. + /// /// # Example /// ``` /// use lattice_qcd_rs::error::ImplementationError; @@ -579,7 +703,7 @@ impl LatticeStateDefault { /// let beta = 1_f64; /// /// let mut simulation = - /// LatticeStateDefault::<4>::new_deterministe(size, beta, number_of_pts, &mut rng)?; + /// LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?; /// /// let spread_parameter = 0.1_f64; /// let mut mc = MetropolisHastingsSweep::new(1, spread_parameter, rng) @@ -590,7 +714,7 @@ impl LatticeStateDefault { /// simulation = simulation.monte_carlo_step(&mut mc)?; /// } /// // the more we advance te more the link matrices - /// // will deviate form SU(3), so we reprojet to SU(3) + /// // will deviate form SU(3), so we reproject to SU(3) /// // every 10 steps. /// simulation.normalize_link_matrices(); /// } @@ -613,7 +737,7 @@ impl LatticeStateDefault { } } - /// Absorbe self anf return the link_matrix as owned + /// Absorbs self anf return the link_matrix as owned #[allow(clippy::missing_const_for_fn)] // false positive pub fn link_matrix_owned(self) -> LinkMatrix { self.link_matrix @@ -624,11 +748,11 @@ impl LatticeStateNew for LatticeStateDefault { type Error = StateInitializationError; fn new( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, link_matrix: LinkMatrix, ) -> Result { - if !lattice.has_compatible_lenght_links(&link_matrix) { + if !lattice.has_compatible_length_links(&link_matrix) { return Err(StateInitializationError::IncompatibleSize); } Ok(Self { @@ -648,7 +772,7 @@ impl LatticeState for LatticeStateDefault { LinkMatrix ); - getter!(lattice, LatticeCyclique); + getter!(lattice, LatticeCyclic); getter_copy!(beta, Real); @@ -662,6 +786,7 @@ impl LatticeState for LatticeStateDefault { } /// Get the default pure gauge Hamiltonian. + /// /// # Panic /// Panic if plaquettes cannot be found fn hamiltonian_links(&self) -> Real { @@ -695,20 +820,20 @@ impl LatticeState for LatticeStateDefault { } } -/// wrapper for a simulation state using leap frog ([`SimulationStateLeap`]) using a synchrone type -/// ([`SimulationStateSynchrone`]). +/// wrapper for a simulation state using leap frog ([`SimulationStateLeap`]) using a synchronous type +/// ([`SimulationStateSynchronous`]). #[derive(Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct SimulationStateLeap where - State: SimulationStateSynchrone + ?Sized, + State: SimulationStateSynchronous + ?Sized, { state: State, } impl SimulationStateLeap where - State: SimulationStateSynchrone + LatticeStateWithEField + ?Sized, + State: SimulationStateSynchronous + LatticeStateWithEField + ?Sized, { getter!( /// get a reference to the state @@ -719,7 +844,7 @@ where /// Create a new SimulationStateLeap directly from a state without applying any modification. /// - /// In most cases wou will prefer to build it using [`LatticeStateNew`] or [`Self::from_synchrone`]. + /// In most cases wou will prefer to build it using [`LatticeStateNew`] or [`Self::from_synchronous`]. pub fn new_from_state(state: State) -> Self { Self { state } } @@ -729,11 +854,11 @@ where &mut self.state } - /// Create a leap state from a sync one by integrating by half a setp the e_field. + /// Create a leap state from a sync one by integrating by half a step the e_field. /// /// # Errors - /// Returns an error if the intregration failed. - pub fn from_synchrone(s: &State, integrator: &I, delta_t: Real) -> Result + /// Returns an error if the integration failed. + pub fn from_synchronous(s: &State, integrator: &I, delta_t: Real) -> Result where I: SymplecticIntegrator + ?Sized, { @@ -749,7 +874,7 @@ where impl Default for SimulationStateLeap where - State: SimulationStateSynchrone + Default + ?Sized, + State: SimulationStateSynchronous + Default + ?Sized, { fn default() -> Self { Self::new_from_state(State::default()) @@ -758,14 +883,14 @@ where impl std::fmt::Display for SimulationStateLeap where - State: SimulationStateSynchrone + std::fmt::Display + ?Sized, + State: SimulationStateSynchronous + std::fmt::Display + ?Sized, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "leapfrog {}", self.state()) } } -impl + LatticeStateWithEField, const D: usize> AsRef +impl + LatticeStateWithEField, const D: usize> AsRef for SimulationStateLeap { fn as_ref(&self) -> &State { @@ -773,7 +898,7 @@ impl + LatticeStateWithEField, const D: us } } -impl + LatticeStateWithEField, const D: usize> AsMut +impl + LatticeStateWithEField, const D: usize> AsMut for SimulationStateLeap { fn as_mut(&mut self) -> &mut State { @@ -783,14 +908,14 @@ impl + LatticeStateWithEField, const D: us /// This state is a leap frog state impl SimulationStateLeapFrog for SimulationStateLeap where - State: SimulationStateSynchrone + LatticeStateWithEField + ?Sized + State: SimulationStateSynchronous + LatticeStateWithEField + ?Sized { } /// We just transmit the function of `State`, there is nothing new. impl LatticeState for SimulationStateLeap where - State: LatticeStateWithEField + SimulationStateSynchrone + ?Sized, + State: LatticeStateWithEField + SimulationStateSynchronous + ?Sized, { const CA: Real = State::CA; @@ -805,7 +930,7 @@ where self.state.set_link_matrix(link_matrix); } - fn lattice(&self) -> &LatticeCyclique { + fn lattice(&self) -> &LatticeCyclic { self.state().lattice() } @@ -820,12 +945,12 @@ where impl LatticeStateWithEFieldNew for SimulationStateLeap where - State: LatticeStateWithEField + SimulationStateSynchrone + LatticeStateWithEFieldNew, + State: LatticeStateWithEField + SimulationStateSynchronous + LatticeStateWithEFieldNew, { type Error = State::Error; fn new( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, e_field: EField, link_matrix: LinkMatrix, @@ -839,7 +964,7 @@ where /// We just transmit the function of `State`, there is nothing new. impl LatticeStateWithEField for SimulationStateLeap where - State: LatticeStateWithEField + SimulationStateSynchrone + ?Sized, + State: LatticeStateWithEField + SimulationStateSynchronous + ?Sized, { project!(hamiltonian_efield, state, Real); @@ -870,7 +995,7 @@ where link: &LatticeLinkCanonical, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { State::derivative_u(link, link_matrix, e_field, lattice) } @@ -879,7 +1004,7 @@ where point: &LatticePoint, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option> { State::derivative_e(point, link_matrix, e_field, lattice) } @@ -888,7 +1013,7 @@ where /// wrapper to implement [`LatticeStateWithEField`] from a [`LatticeState`] using /// the default implementation of conjugate momenta. /// -/// It also implement [`SimulationStateSynchrone`]. +/// It also implement [`SimulationStateSynchronous`]. #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct LatticeStateEFSyncDefault @@ -911,8 +1036,8 @@ impl LatticeStateEFSyncDefault where State: LatticeState + ?Sized, { - /// Absorbe self and return the state as owned. - /// It essentialy deconstruct the structure. + /// Absorbs self and return the state as owned. + /// It essentially deconstruct the structure. pub fn state_owned(self) -> State where State: Sized, @@ -925,22 +1050,26 @@ where &self.lattice_state } - /// Get a mutlable reference to the state. + /// Get a mutable reference to the state. pub fn lattice_state_mut(&mut self) -> &mut State { &mut self.lattice_state } + /// Take a state and generate a new random one and try projecting it to the Gauss law. + /// /// # Panic - /// Panics if N(0, 0.5/beta ) is not a valide distribution (for exampple beta = 0) + /// Panics if N(0, 0.5/beta ) is not a valid distribution (for example beta = 0). + /// Panics if the field could not be projected to the Gauss law. pub fn new_random_e_state(lattice_state: State, rng: &mut impl rand::Rng) -> Self where State: Sized, { let d = rand_distr::Normal::new(0_f64, 0.5_f64 / lattice_state.beta()) - .expect("Distribution not valide, check Beta."); - let e_field = EField::new_deterministe(lattice_state.lattice(), rng, &d) + .expect("Distribution not valid, check Beta."); + let e_field = EField::new_determinist(lattice_state.lattice(), rng, &d) .project_to_gauss(lattice_state.link_matrix(), lattice_state.lattice()) .unwrap(); + // TODO error management Self { lattice_state, e_field, @@ -989,19 +1118,19 @@ where /// /// Single threaded generation with a given random number generator. /// `size` is the size parameter of the lattice and `number_of_points` is the number of points - /// in each spatial dimension of the lattice. See [`LatticeCyclique::new`] for more info. + /// in each spatial dimension of the lattice. See [`LatticeCyclic::new`] for more info. /// /// useful to reproduce a set of data but slower than /// [`LatticeStateEFSyncDefault::new_random_threaded`]. /// /// # Errors - /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. + /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid + /// for [`LatticeCyclic`]. /// Or propagates the error form [`Self::new`]. /// /// # Example /// ``` - /// # use lattice_qcd_rs::{simulation::{LatticeStateEFSyncDefault, LatticeStateDefault}, lattice::LatticeCyclique}; + /// # use lattice_qcd_rs::{simulation::{LatticeStateEFSyncDefault, LatticeStateDefault}, lattice::LatticeCyclic}; /// use rand::{SeedableRng,rngs::StdRng}; /// /// let mut rng_1 = StdRng::seed_from_u64(0); @@ -1009,11 +1138,11 @@ where /// // They have the same seed and should generate the same numbers /// let distribution = rand::distributions::Uniform::from(-1_f64..1_f64); /// assert_eq!( - /// LatticeStateEFSyncDefault::, 4>::new_deterministe(1_f64, 1_f64, 4, &mut rng_1, &distribution).unwrap(), - /// LatticeStateEFSyncDefault::, 4>::new_deterministe(1_f64, 1_f64, 4, &mut rng_2, &distribution).unwrap() + /// LatticeStateEFSyncDefault::, 4>::new_determinist(1_f64, 1_f64, 4, &mut rng_1, &distribution).unwrap(), + /// LatticeStateEFSyncDefault::, 4>::new_determinist(1_f64, 1_f64, 4, &mut rng_2, &distribution).unwrap() /// ); /// ``` - pub fn new_deterministe( + pub fn new_determinist( size: Real, beta: Real, number_of_points: usize, @@ -1023,19 +1152,19 @@ where where R: rand::Rng + ?Sized, { - let lattice = LatticeCyclique::new(size, number_of_points)?; - let e_field = EField::new_deterministe(&lattice, rng, d); - let link_matrix = LinkMatrix::new_deterministe(&lattice, rng); + let lattice = LatticeCyclic::new(size, number_of_points)?; + let e_field = EField::new_determinist(&lattice, rng, d); + let link_matrix = LinkMatrix::new_determinist(&lattice, rng); Self::new(lattice, beta, e_field, link_matrix, 0) } /// Generate a configuration with cold e_field and hot link matrices /// /// # Errors - /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. + /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid + /// for [`LatticeCyclic`]. /// Or propagates the error form [`Self::new`]. - pub fn new_deterministe_cold_e_hot_link( + pub fn new_determinist_cold_e_hot_link( size: Real, beta: Real, number_of_points: usize, @@ -1044,9 +1173,9 @@ where where R: rand::Rng + ?Sized, { - let lattice = LatticeCyclique::new(size, number_of_points)?; + let lattice = LatticeCyclic::new(size, number_of_points)?; let e_field = EField::new_cold(&lattice); - let link_matrix = LinkMatrix::new_deterministe(&lattice, rng); + let link_matrix = LinkMatrix::new_determinist(&lattice, rng); Self::new(lattice, beta, e_field, link_matrix, 0) } @@ -1056,15 +1185,15 @@ where /// It meas that the link matrices are set to the identity and electrical field are set to 0. /// /// # Errors - /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. + /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid + /// for [`LatticeCyclic`]. /// Or propagates the error form [`Self::new`]. pub fn new_cold( size: Real, beta: Real, number_of_points: usize, ) -> Result>::Error> { - let lattice = LatticeCyclique::new(size, number_of_points)?; + let lattice = LatticeCyclic::new(size, number_of_points)?; let link_matrix = LinkMatrix::new_cold(&lattice); let e_field = EField::new_cold(&lattice); Self::new(lattice, beta, e_field, link_matrix, 0) @@ -1080,12 +1209,12 @@ where /// /// Multi threaded generation of random data. Due to the non deterministic way threads /// operate a set cannot be reproduce easily, In that case use - /// [`LatticeStateEFSyncDefault::new_deterministe`]. + /// [`LatticeStateEFSyncDefault::new_determinist`]. /// /// # Errors - /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalide - /// for [`LatticeCyclique`]. - /// Return [`ThreadError::ThreadNumberIncorect`] if `number_of_points = 0`. + /// Return [`StateInitializationError::LatticeInitializationError`] if the parameter is invalid + /// for [`LatticeCyclic`]. + /// Return [`ThreadError::ThreadNumberIncorrect`] if `number_of_points = 0`. /// Returns an error if a thread panicked. Finally, propagates the error form [`Self::new`]. pub fn new_random_threaded( size: Real, @@ -1099,15 +1228,15 @@ where { if number_of_thread == 0 { return Err(ThreadedStateInitializationError::ThreadingError( - ThreadError::ThreadNumberIncorect, + ThreadError::ThreadNumberIncorrect, )); } else if number_of_thread == 1 { let mut rng = rand::thread_rng(); - return Self::new_deterministe(size, beta, number_of_points, &mut rng, d) + return Self::new_determinist(size, beta, number_of_points, &mut rng, d) .map_err(|err| err.into()); } - let lattice = LatticeCyclique::new(size, number_of_points).map_err(|err| { + let lattice = LatticeCyclic::new(size, number_of_points).map_err(|err| { ThreadedStateInitializationError::StateInitializationError(err.into()) })?; thread::scope(|s| { @@ -1119,7 +1248,7 @@ where ThreadAnyError::Panic(vec![err]).into(), ) })?; - // TODO not very clean: imporve + // TODO not very clean: improve Self::new(lattice, beta, e_field, link_matrix, 0) .map_err(ThreadedStateInitializationError::StateInitializationError) }) @@ -1132,7 +1261,7 @@ where } /// This is an sync State -impl SimulationStateSynchrone for LatticeStateEFSyncDefault +impl SimulationStateSynchronous for LatticeStateEFSyncDefault where State: LatticeState + Clone + ?Sized, Self: LatticeStateWithEField, @@ -1155,7 +1284,7 @@ where self.lattice_state.set_link_matrix(link_matrix); } - fn lattice(&self) -> &LatticeCyclique { + fn lattice(&self) -> &LatticeCyclic { self.lattice_state.lattice() } @@ -1181,13 +1310,13 @@ where /// amount of data compared to lattice it fails to create the state. /// `t` is the number of time the simulation ran. i.e. the time sate. fn new( - lattice: LatticeCyclique, + lattice: LatticeCyclic, beta: Real, e_field: EField, link_matrix: LinkMatrix, t: usize, ) -> Result { - if !lattice.has_compatible_lenght_e_field(&e_field) { + if !lattice.has_compatible_length_e_field(&e_field) { return Err(StateInitializationError::IncompatibleSize.into()); } let lattice_state_r = State::new(lattice, beta, link_matrix); @@ -1249,7 +1378,7 @@ where link: &LatticeLinkCanonical, link_matrix: &LinkMatrix, e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option { let c = Complex::new(0_f64, (2_f64 * Self::CA).sqrt()); let u_i = link_matrix.matrix(&LatticeLink::from(*link), lattice)?; @@ -1262,7 +1391,7 @@ where point: &LatticePoint, link_matrix: &LinkMatrix, _e_field: &EField, - lattice: &LatticeCyclique, + lattice: &LatticeCyclic, ) -> Option> { let c = -(2_f64 / Self::CA).sqrt(); let dir_pos = Direction::::positive_directions(); diff --git a/src/statistics/distribution.rs b/src/statistics/distribution.rs index 9c5d3914..9763413b 100644 --- a/src/statistics/distribution.rs +++ b/src/statistics/distribution.rs @@ -57,14 +57,14 @@ where rand::distributions::OpenClosed01: Distribution, { getter_copy!( - /// return the parameter `a`. + /// Returns the parameter `a`. pub, param_exp, T ); /// Create the distribution. `param_exp` should be strictly greater than 0 an be finite and a number. - /// Otherwise return None. + /// Otherwise return [`None`]. pub fn new(param_exp: T) -> Option { if param_exp.le(&T::zero()) || param_exp.is_infinite() || param_exp.is_nan() { return None; @@ -180,14 +180,14 @@ where Uniform: Distribution, { getter_copy!( - /// return the parameter `param_exp`. + /// Returns the parameter `param_exp`. pub, param_exp, T ); /// Create the distribution. `param_exp` should be strictly greater than 0 an be finite and a number. - /// Otherwise return None. + /// Otherwise return [`None`]. pub fn new(param_exp: T) -> Option { if param_exp.le(&T::zero()) || param_exp.is_infinite() || param_exp.is_nan() { return None; @@ -201,10 +201,10 @@ impl Distribution for HeatBathDistribution { where R: rand::Rng + ?Sized, { - // TODO make a functrion to reduce copy of code with su2::get_random_su2_close_to_unity + // TODO make a function to reduce copy of code with su2::get_random_su2_close_to_unity - let distr_norm = HeatBathDistributionNorm::new(self.param_exp()).expect("unreacheable"); - // unreacheable because self.param_exp() > 0 which Create the distribution + let distr_norm = HeatBathDistributionNorm::new(self.param_exp()).expect("unreachable"); + // unreachable because self.param_exp() > 0 which Create the distribution let x0: f64 = rng.sample(&distr_norm); let uniform = Uniform::new(-1_f64, 1_f64); let mut x_unorm = na::Vector3::from_fn(|_, _| rng.sample(&uniform)); @@ -212,8 +212,8 @@ impl Distribution for HeatBathDistribution { x_unorm = na::Vector3::from_fn(|_, _| rng.sample(&uniform)); } let x = - x_unorm.try_normalize(f64::EPSILON).expect("unreacheable") * (1_f64 - x0 * x0).sqrt(); - // unreacheable because the while loop above guarentee that the norm is bigger than [`f64::EPSILON`] + x_unorm.try_normalize(f64::EPSILON).expect("unreachable") * (1_f64 - x0 * x0).sqrt(); + // unreachable because the while loop above guarantee that the norm is bigger than [`f64::EPSILON`] su2::complex_matrix_from_vec(x0, x) } } @@ -308,7 +308,7 @@ where ); /// Create the distribution. `param_exp` should be strictly greater than 0 an be finite and a number. - /// Otherwise return None. + /// Otherwise return [`None`]. pub fn new(param_exp: T) -> Option { if param_exp.le(&T::zero()) || param_exp.is_infinite() || param_exp.is_nan() { return None; diff --git a/src/statistics/mod.rs b/src/statistics/mod.rs index 49d5ec91..a1ccd6a1 100644 --- a/src/statistics/mod.rs +++ b/src/statistics/mod.rs @@ -40,7 +40,7 @@ where /// Compute the mean from a [`rayon::iter::IndexedParallelIterator`]. If you want /// to use reference use [`mean_par_iter`]. /// It uses the power of the parallel iterator to do the computation and is -/// particullary usefull in combination of a map. +/// particularly useful in combination of a map. /// /// # Example /// ``` @@ -129,7 +129,7 @@ where /// Compute the mean and variance (squared of standard deviation) from /// a [`rayon::iter::IndexedParallelIterator`]. /// Provides better performance than computing the mean and variation separately -/// as this methode comsume the iterator only once. +/// as this method consume the iterator only once. /// /// The alternative for iterators returning non-references /// is [`mean_and_variance_par_iter_val`] @@ -155,7 +155,7 @@ where /// Compute the mean and variance (squared of standard deviation) from /// a [`rayon::iter::IndexedParallelIterator`] by value. /// Provides better performance than computing the mean and variation separately as -/// this methode comsume the iterator only once. +/// this method consume the iterator only once. /// /// The alternative for iterators returning references is [`mean_and_variance_par_iter`]. /// # Example @@ -395,7 +395,7 @@ where [mean, variance] } -/// compute the mean the statistocal error on this value a slice. +/// compute the mean the statistical error on this value a slice. /// /// The statistical error is defined by `sqrt(variance / len)`. pub fn mean_with_error(data: &[f64]) -> [f64; 2] { diff --git a/src/su2.rs b/src/su2.rs index d7362755..93e38395 100644 --- a/src/su2.rs +++ b/src/su2.rs @@ -1,6 +1,7 @@ //! module for SU(2) matrix -use rand_distr::Distribution; +use rand::Rng; +use rand_distr::{Distribution, Uniform}; use super::{CMatrix2, Complex, ComplexField, Real, I, ONE, ZERO}; @@ -49,9 +50,33 @@ pub const PAULI_MATRICES: [&CMatrix2; 3] = [&PAULI_1, &PAULI_2, &PAULI_3]; /// Get a radom SU(2) matrix close the 1 or -1. /// -/// Note that it diverges from SU(2) sligthly. -/// `spread_parameter` should be between between 0 and 1 both excluded to generate valide data. +/// Note that it diverges from SU(2) slightly. +/// `spread_parameter` should be between between 0 and 1 both excluded to generate valid data. /// outside this bound it will not panic but can have unexpected results. +/// +/// # Example +/// /// # Example +/// ``` +/// # use lattice_qcd_rs::{assert_matrix_is_su_2,su2::random_su2_close_to_unity}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// for _ in 0..10 { +/// assert_matrix_is_su_2!( +/// random_su2_close_to_unity(0.000_000_001_f64, &mut rng), +/// 0.000_000_1_f64 +/// ); +/// } +/// ``` +/// but it will be not close to SU(2) up to [`f64::EPSILON`]. +/// ```should_panic +/// # use lattice_qcd_rs::{assert_matrix_is_su_2,su2::random_su2_close_to_unity}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// assert_matrix_is_su_2!( +/// random_su2_close_to_unity(0.000_000_001_f64, &mut rng), +/// f64::EPSILON * 40_f64 +/// ); +/// ``` pub fn random_su2_close_to_unity(spread_parameter: Real, rng: &mut R) -> CMatrix2 where R: rand::Rng + ?Sized, @@ -59,6 +84,7 @@ where let d = rand::distributions::Uniform::new(-1_f64, 1_f64); let r = na::Vector3::::from_fn(|_, _| d.sample(rng)); let x = r.try_normalize(f64::EPSILON).unwrap_or(r) * spread_parameter; + // always exists, unwrap is safe let d_sign = rand::distributions::Bernoulli::new(0.5_f64).unwrap(); // we could have use the spread_parameter but it is safer to use the norm of x let x0_unsigned = (1_f64 - x.norm_squared()).sqrt(); @@ -74,6 +100,37 @@ where } /// Return `x0 1 + i x_i * \sigma_i`. +/// +/// # Examples +/// ``` +/// use lattice_qcd_rs::{ +/// assert_eq_matrix, +/// su2::{complex_matrix_from_vec, PAULI_1}, +/// CMatrix2, +/// }; +/// +/// let m = complex_matrix_from_vec(1.0, nalgebra::Vector3::new(0_f64, 0_f64, 0_f64)); +/// assert_eq_matrix!( +/// m, +/// CMatrix2::new( +/// nalgebra::Complex::new(1_f64, 0_f64), +/// nalgebra::Complex::new(0_f64, 0_f64), +/// nalgebra::Complex::new(0_f64, 0_f64), +/// nalgebra::Complex::new(1_f64, 0_f64) +/// ), +/// f64::EPSILON +/// ); +/// +/// let m = complex_matrix_from_vec(0.5_f64, nalgebra::Vector3::new(1_f64, 0_f64, 0_f64)); +/// let m2 = CMatrix2::new( +/// nalgebra::Complex::new(1_f64, 0_f64), +/// nalgebra::Complex::new(0_f64, 0_f64), +/// nalgebra::Complex::new(0_f64, 0_f64), +/// nalgebra::Complex::new(1_f64, 0_f64), +/// ) * nalgebra::Complex::new(0.5_f64, 0_f64) +/// + PAULI_1 * nalgebra::Complex::new(0_f64, 1_f64); +/// assert_eq_matrix!(m, m2, f64::EPSILON); +/// ``` pub fn complex_matrix_from_vec(x0: Real, x: na::Vector3) -> CMatrix2 { CMatrix2::identity() * Complex::from(x0) + x.iter() @@ -82,14 +139,44 @@ pub fn complex_matrix_from_vec(x0: Real, x: na::Vector3) -> CMatrix2 { .sum::() } -/// Take any 2x2 matrix and project it to a matric `X` such that `X / X.determinant().modulus().sqrt()` +/// Take any 2x2 matrix and project it to a matrix `X` such that `X / X.determinant().modulus().sqrt()` /// is SU(2). +/// +/// # Examples +/// see [`project_to_su2`] +/// ``` +/// # use lattice_qcd_rs::{su2::{project_to_su2_unorm, random_su2},CMatrix2, Complex, assert_eq_matrix}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// let m = CMatrix2::zeros(); +/// assert_eq_matrix!(project_to_su2_unorm(m), m, f64::EPSILON); +/// ``` +// TODO more example pub fn project_to_su2_unorm(m: CMatrix2) -> CMatrix2 { m - m.adjoint() + CMatrix2::identity() * m.trace().conjugate() } /// Project the matrix to SU(2). Return the identity if the norm after unormalize is /// subnormal (see[`f64::is_normal`]). +/// +/// # Examples +/// ``` +/// # use lattice_qcd_rs::{su2::{project_to_su2, random_su2, random_matrix_2},CMatrix2, Complex, assert_eq_matrix, assert_matrix_is_su_2}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// let m = CMatrix2::zeros(); +/// assert_eq_matrix!(project_to_su2(m), CMatrix2::identity(), f64::EPSILON); +/// for _ in 0..10 { +/// let m = random_su2(&mut rng); +/// assert_eq_matrix!(project_to_su2(m * Complex::new(0.5_f64, 0_f64)), m, 4_f64 * f64::EPSILON); +/// assert_eq_matrix!(project_to_su2(m), m, 4_f64 * f64::EPSILON); +/// assert_matrix_is_su_2!(project_to_su2(m), 4_f64 * f64::EPSILON); +/// } +/// for _ in 0..10 { +/// let m = random_matrix_2(&mut rng); +/// assert_matrix_is_su_2!(project_to_su2(m), 4_f64 * f64::EPSILON) +/// } +/// ``` pub fn project_to_su2(m: CMatrix2) -> CMatrix2 { let m = project_to_su2_unorm(m); if m.determinant().modulus().is_normal() { @@ -101,6 +188,15 @@ pub fn project_to_su2(m: CMatrix2) -> CMatrix2 { } /// Get an Uniformly random SU(2) matrix. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{assert_matrix_is_su_2,su2::random_su2}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// for _ in 0..10 { +/// assert_matrix_is_su_2!(random_su2(&mut rng), 4_f64 * f64::EPSILON); +/// } pub fn random_su2(rng: &mut Rng) -> CMatrix2 where Rng: rand::Rng + ?Sized, @@ -120,11 +216,33 @@ where } /// Return wether the input matrix is SU(2) up to epsilon. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{su2::{is_matrix_su2, random_su2}, CMatrix2}; +/// # use rand::SeedableRng; +/// # use nalgebra::{Complex}; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// +/// assert!(is_matrix_su2(&random_su2(&mut rng), 4_f64 * f64::EPSILON)); +/// assert!(!is_matrix_su2(&CMatrix2::zeros(), 4_f64 * f64::EPSILON)); +/// assert!(!is_matrix_su2( +/// &(random_su2(&mut rng) * Complex::new(0.5_f64, 1.7_f64)), +/// 4_f64 * f64::EPSILON +/// )); +/// ``` pub fn is_matrix_su2(m: &CMatrix2, epsilon: f64) -> bool { ((m.determinant() - Complex::from(1_f64)).modulus_squared() < epsilon) && ((m * m.adjoint() - CMatrix2::identity()).norm() < epsilon) } +#[doc(hidden)] +/// Crate a random 2x2 Matrix +pub fn random_matrix_2(rng: &mut R) -> CMatrix2 { + let d = Uniform::from(-10_f64..10_f64); + CMatrix2::from_fn(|_, _| Complex::new(d.sample(rng), d.sample(rng))) +} + #[cfg(test)] mod test { use rand::SeedableRng; diff --git a/src/su3.rs b/src/su3.rs index e425173c..be651cb0 100644 --- a/src/su3.rs +++ b/src/su3.rs @@ -7,7 +7,8 @@ use std::iter::FusedIterator; use na::{base::allocator::Allocator, ComplexField, DefaultAllocator, OMatrix}; -use rand_distr::Distribution; +use rand::Rng; +use rand_distr::{Distribution, Uniform}; use super::{ field::Su3Adjoint, su2, utils, utils::FactorialNumber, CMatrix2, CMatrix3, Complex, Real, I, @@ -217,7 +218,7 @@ where { fn exp(self) -> OMatrix { let decomposition = self.schur(); - // a complex matrix is always diagonalisable + // a complex matrix is always diagonalizable let eigens = decomposition.eigenvalues().unwrap(); let new_matrix = Self::from_diagonal(&eigens.map(|el| el.exp())); let (q, _) = decomposition.unpack(); @@ -226,12 +227,14 @@ where } } -/// Create a [`Matrix3`] of the form `[v1, v2, v1* x v2*]` where v1* is the conjugate of v1 and -/// `x` is the cross product +/// Create a [`super::CMatrix3`] of the form `[v1, v2, v1* x v2*]` where v1* is the conjugate of v1 and +/// `x` is the cross product. +/// /// # Example -/// ```ignore +/// ``` /// # use nalgebra::{Vector3, Complex, Matrix3}; /// # use lattice_qcd_rs::{assert_eq_matrix}; +/// # use lattice_qcd_rs::su3::create_matrix_from_2_vector; /// let v1 = Vector3::new( /// Complex::new(1_f64, 0_f64), /// Complex::new(0_f64, 0_f64), @@ -271,13 +274,9 @@ where /// Complex::new(0_f64, 0_f64), /// Complex::new(0_f64, -1_f64), /// ); -/// assert_eq_matrix!( -/// m, -/// create_matrix_from_2_vector(v1, v2), -/// 0.000_000_1_f64 -/// ); +/// assert_eq_matrix!(m, create_matrix_from_2_vector(v1, v2), 0.000_000_1_f64); /// ``` -fn create_matrix_from_2_vector( +pub fn create_matrix_from_2_vector( v1: na::Vector3, v2: na::Vector3, ) -> na::Matrix3 { @@ -296,6 +295,7 @@ fn ortho_matrix_from_2_vector(v1: na::Vector3, v2: na::Vector3 } /// Try orthonormalize the given matrix. +// TODO example pub fn orthonormalize_matrix(matrix: &CMatrix3) -> CMatrix3 { let v1 = na::Vector3::from_iterator(matrix.column(0).iter().copied()); let v2 = na::Vector3::from_iterator(matrix.column(1).iter().copied()); @@ -303,11 +303,22 @@ pub fn orthonormalize_matrix(matrix: &CMatrix3) -> CMatrix3 { } /// Orthonormalize the given matrix by mutating its content. +// TODO example pub fn orthonormalize_matrix_mut(matrix: &mut CMatrix3) { *matrix = orthonormalize_matrix(matrix); } -/// Generate Uniformly distributed SU(3) matrix +/// Generate Uniformly distributed SU(3) matrix. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{assert_matrix_is_su_3,su3::random_su3}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// for _ in 0..10 { +/// assert_matrix_is_su_3!(random_su3(&mut rng), 9_f64 * f64::EPSILON); +/// } +/// ``` pub fn random_su3(rng: &mut Rng) -> CMatrix3 where Rng: rand::Rng + ?Sized, @@ -315,10 +326,10 @@ where rand_su3_with_dis(rng, &rand::distributions::Uniform::new(-1_f64, 1_f64)) } -/// get a random SU3 with the given distribution. +/// Get a random SU3 with the given distribution. /// /// The given distribution can be quite opaque on the distribution of the SU(3) matrix. -/// For a matrix Uniformly distributed amoung SU(3) use [`get_random_su3`]. +/// For a matrix Uniformly distributed among SU(3) use [`get_random_su3`]. /// For a matrix close to unity use [`get_random_su3_close_to_unity`] fn rand_su3_with_dis(rng: &mut Rng, d: &impl rand_distr::Distribution) -> CMatrix3 where @@ -345,9 +356,33 @@ where /// Get a radom SU(3) matrix close to `[get_r] (+/- 1) * [get_s] (+/- 1) * [get_t] (+/- 1)`. /// -/// Note that it diverges from SU(3) sligthly. -/// `spread_parameter` should be between between 0 and 1 both excluded to generate valide data. -/// outside this boud it will not panic but can have unexpected results. +/// Note that it diverges from SU(3) slightly. +/// `spread_parameter` should be between between 0 and 1 both excluded to generate valid data. +/// outside this bound it will not panic but can have unexpected results. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{assert_matrix_is_su_3,su3::random_su3_close_to_unity}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// for _ in 0..10 { +/// assert_matrix_is_su_3!( +/// random_su3_close_to_unity(0.000_000_001_f64, &mut rng), +/// 0.000_000_1_f64 +/// ); +/// } +/// ``` +/// but it will be not close to SU(3) up to [`f64::EPSILON`]. +/// ```should_panic +/// # use lattice_qcd_rs::{assert_matrix_is_su_3,su3::random_su3_close_to_unity}; +/// # use rand::SeedableRng; +/// # let mut rng = rand::rngs::StdRng::seed_from_u64(0); +/// assert_matrix_is_su_3!( +/// random_su3_close_to_unity(0.000_000_001_f64, &mut rng), +/// f64::EPSILON * 180_f64 +/// ); +/// ``` +// TODO review example epsilon pub fn random_su3_close_to_unity(spread_parameter: Real, rng: &mut R) -> CMatrix3 where R: rand::Rng + ?Sized, @@ -364,6 +399,33 @@ where } /// Embed a Matrix2 inside Matrix3 leaving the last row and column be the same as identity. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_r, Complex, assert_eq_matrix}; +/// let m1 = CMatrix2::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(3_f64), +/// Complex::from(4_f64), +/// ); +/// +/// let m2 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// Complex::from(0_f64), +/// // --- +/// Complex::from(3_f64), +/// Complex::from(4_f64), +/// Complex::from(0_f64), +/// // --- +/// Complex::from(0_f64), +/// Complex::from(0_f64), +/// Complex::from(1_f64), +/// ); +/// assert_eq_matrix!(get_r(m1), m2, f64::EPSILON); +/// ``` pub fn get_r(m: CMatrix2) -> CMatrix3 { CMatrix3::new( m[(0, 0)], @@ -381,6 +443,33 @@ pub fn get_r(m: CMatrix2) -> CMatrix3 { } /// Embed a Matrix2 inside Matrix3 leaving the second row and column be the same as identity. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_s, Complex, assert_eq_matrix}; +/// let m1 = CMatrix2::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(3_f64), +/// Complex::from(4_f64), +/// ); +/// +/// let m2 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(0_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(0_f64), +/// Complex::from(1_f64), +/// Complex::from(0_f64), +/// // --- +/// Complex::from(3_f64), +/// Complex::from(0_f64), +/// Complex::from(4_f64), +/// ); +/// assert_eq_matrix!(get_s(m1), m2, f64::EPSILON); +/// ``` pub fn get_s(m: CMatrix2) -> CMatrix3 { CMatrix3::new( m[(0, 0)], @@ -398,6 +487,33 @@ pub fn get_s(m: CMatrix2) -> CMatrix3 { } /// Embed a Matrix2 inside Matrix3 leaving the first row and column be the same as identity. +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_t, Complex, assert_eq_matrix}; +/// let m1 = CMatrix2::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(3_f64), +/// Complex::from(4_f64), +/// ); +/// +/// let m2 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(0_f64), +/// Complex::from(0_f64), +/// // --- +/// Complex::from(0_f64), +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(0_f64), +/// Complex::from(3_f64), +/// Complex::from(4_f64), +/// ); +/// assert_eq_matrix!(get_t(m1), m2, f64::EPSILON); +/// ``` pub fn get_t(m: CMatrix2) -> CMatrix3 { CMatrix3::new( ONE, @@ -414,7 +530,33 @@ pub fn get_t(m: CMatrix2) -> CMatrix3 { ) } -/// get the [`CMatrix2`] sub block corresponing to [`get_r`] +/// get the [`CMatrix2`] sub block corresponding to [`get_r`] +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_sub_block_r, Complex, assert_eq_matrix}; +/// let m1 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// Complex::from(3_f64), +/// // --- +/// Complex::from(4_f64), +/// Complex::from(5_f64), +/// Complex::from(6_f64), +/// // --- +/// Complex::from(7_f64), +/// Complex::from(8_f64), +/// Complex::from(9_f64), +/// ); +/// let m2 = CMatrix2::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// // --- +/// Complex::from(4_f64), +/// Complex::from(5_f64), +/// ); +/// assert_eq_matrix!(get_sub_block_r(m1), m2, f64::EPSILON); +/// ``` pub fn get_sub_block_r(m: CMatrix3) -> CMatrix2 { CMatrix2::new( m[(0, 0)], @@ -425,7 +567,33 @@ pub fn get_sub_block_r(m: CMatrix3) -> CMatrix2 { ) } -/// get the [`CMatrix2`] sub block corresponing to [`get_s`] +/// get the [`CMatrix2`] sub block corresponding to [`get_s`] +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_sub_block_s, Complex, assert_eq_matrix}; +/// let m1 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// Complex::from(3_f64), +/// // --- +/// Complex::from(4_f64), +/// Complex::from(5_f64), +/// Complex::from(6_f64), +/// // --- +/// Complex::from(7_f64), +/// Complex::from(8_f64), +/// Complex::from(9_f64), +/// ); +/// let m2 = CMatrix2::new( +/// Complex::from(1_f64), +/// Complex::from(3_f64), +/// // --- +/// Complex::from(7_f64), +/// Complex::from(9_f64), +/// ); +/// assert_eq_matrix!(get_sub_block_s(m1), m2, f64::EPSILON); +/// ``` pub fn get_sub_block_s(m: CMatrix3) -> CMatrix2 { CMatrix2::new( m[(0, 0)], @@ -436,7 +604,33 @@ pub fn get_sub_block_s(m: CMatrix3) -> CMatrix2 { ) } -/// get the [`CMatrix2`] sub block corresponing to [`get_t`] +/// Get the [`CMatrix2`] sub block corresponding to [`get_t`] +/// +/// # Example +/// ``` +/// # use lattice_qcd_rs::{CMatrix3, CMatrix2, su3::get_sub_block_t, Complex, assert_eq_matrix}; +/// let m1 = CMatrix3::new( +/// Complex::from(1_f64), +/// Complex::from(2_f64), +/// Complex::from(3_f64), +/// // --- +/// Complex::from(4_f64), +/// Complex::from(5_f64), +/// Complex::from(6_f64), +/// // --- +/// Complex::from(7_f64), +/// Complex::from(8_f64), +/// Complex::from(9_f64), +/// ); +/// let m2 = CMatrix2::new( +/// Complex::from(5_f64), +/// Complex::from(6_f64), +/// // --- +/// Complex::from(8_f64), +/// Complex::from(9_f64), +/// ); +/// assert_eq_matrix!(get_sub_block_t(m1), m2, f64::EPSILON); +/// ``` pub fn get_sub_block_t(m: CMatrix3) -> CMatrix2 { CMatrix2::new( m[(1, 1)], @@ -447,25 +641,26 @@ pub fn get_sub_block_t(m: CMatrix3) -> CMatrix2 { ) } -/// Get the unormalize SU(2) sub matrix of an SU(3) matrix correspondig to the "r" sub block see -/// [`get_sub_block_r`] and [`get_r`]. +/// Get the unormalize SU(2) sub matrix of an SU(3) matrix corresponding to the "r" sub block see +/// [`get_sub_block_r`] and [`su2::project_to_su2_unorm`]. pub fn get_su2_r_unorm(input: CMatrix3) -> CMatrix2 { su2::project_to_su2_unorm(get_sub_block_r(input)) } -/// Get the unormalize SU(2) sub matrix of an SU(3) matrix correspondig to the "s" sub block see -/// [`get_sub_block_s`] and [`get_s`]. +/// Get the unormalize SU(2) sub matrix of an SU(3) matrix corresponding to the "s" sub block see +/// [`get_sub_block_s`] and [`su2::project_to_su2_unorm`]. pub fn get_su2_s_unorm(input: CMatrix3) -> CMatrix2 { su2::project_to_su2_unorm(get_sub_block_s(input)) } -/// Get the unormalize SU(2) sub matrix of an SU(3) matrix correspondig to the "t" sub block see -/// [`get_sub_block_t`] and [`get_t`]. +/// Get the unormalize SU(2) sub matrix of an SU(3) matrix corresponding to the "t" sub block see +/// [`get_sub_block_t`] and [`su2::project_to_su2_unorm`]. pub fn get_su2_t_unorm(input: CMatrix3) -> CMatrix2 { su2::project_to_su2_unorm(get_sub_block_t(input)) } /// Get the three unormalize sub SU(2) matrix of the given SU(3) matrix, ordered `r, s, t` +/// see [`get_sub_block_r`], [`get_sub_block_s`] and [`get_sub_block_t`] pub fn extract_su2_unorm(m: CMatrix3) -> [CMatrix2; 3] { [get_su2_r_unorm(m), get_su2_s_unorm(m), get_su2_t_unorm(m)] } @@ -536,7 +731,7 @@ pub fn factorial_size_for_exp() -> usize { /// Size of the array for FactorialStorageStatic const FACTORIAL_STORAGE_STAT_SIZE: usize = utils::MAX_NUMBER_FACTORIAL + 1; -/// static store for factorial number +/// Static store for factorial number. #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] struct FactorialStorageStatic { data: [FactorialNumber; FACTORIAL_STORAGE_STAT_SIZE], @@ -578,7 +773,7 @@ impl FactorialStorageStatic { self.data.iter() } - /// Get the slice of factoral number. + /// Get the slice of factorial number. pub const fn as_slice(&self) -> &[FactorialNumber; FACTORIAL_STORAGE_STAT_SIZE] { &self.data } @@ -622,7 +817,7 @@ impl AsRef<[FactorialNumber; FACTORIAL_STORAGE_STAT_SIZE]> for FactorialStorageS /// the set if for all number `N` such that `\frac{1}{(N-7)!} >= \mathrm{f64::EPSILON}` const FACTORIAL_STORAGE_STAT: FactorialStorageStatic = FactorialStorageStatic::new(); -/// number of step for the computation of matric exponential using the Cayley–Hamilton theorem. +/// number of step for the computation of matrix exponential using the Cayley–Hamilton theorem. const N: usize = 26; /// give the SU3 matrix from the adjoint rep, i.e compute `exp(i v^a T^a )` @@ -671,8 +866,8 @@ pub fn su3_exp_i(su3_adj: Su3Adjoint) -> CMatrix3 { /// exp(i X). /// /// # Panic -/// The input matrix must be an su(3) (Lie algebra of SU(3)) matrix or approximatively su(3), -/// otherwise the function will panic in debug mod, in release the ouptut gives unexpected values. +/// The input matrix must be an su(3) (Lie algebra of SU(3)) matrix or approximately su(3), +/// otherwise the function will panic in debug mod, in release the output gives unexpected values. /// ```should_panic /// use lattice_qcd_rs::{ /// assert_eq_matrix, @@ -751,8 +946,8 @@ pub fn su3_exp_r(su3_adj: Su3Adjoint) -> CMatrix3 { /// [here](https://github.com/sa2c/OpenQCD-AVX512/blob/master/doc/su3_fcts.pdf) or by downloading a release. /// /// # Panic -/// The input matrix must be an su(3) (Lie algebra of SU(3)) matrix or approximatively su(3), -/// otherwise the function will panic in debug mod, in release the ouptut gives unexpected values. +/// The input matrix must be an su(3) (Lie algebra of SU(3)) matrix or approximately su(3), +/// otherwise the function will panic in debug mod, in release the output gives unexpected values. /// ```should_panic /// use lattice_qcd_rs::{ /// assert_eq_matrix, @@ -792,16 +987,24 @@ pub fn matrix_su3_exp_r(matrix: CMatrix3) -> CMatrix3 { } /// Return wether the input matrix is SU(3) up to epsilon. +// TODO example pub fn is_matrix_su3(m: &CMatrix3, epsilon: f64) -> bool { ((m.determinant() - Complex::from(1_f64)).modulus_squared() < epsilon) && ((m * m.adjoint() - CMatrix3::identity()).norm() < epsilon) } -/// Returns wether the given matric is in the lie algebra su(3) that generates SU(3) up to epsilon. +/// Returns wether the given matrix is in the lie algebra su(3) that generates SU(3) up to epsilon. pub fn is_matrix_su3_lie(matrix: &CMatrix3, epsilon: Real) -> bool { matrix.trace().modulus() < epsilon && (matrix - matrix.adjoint()).norm() < epsilon } +#[doc(hidden)] +/// Crate a random 3x3 Matrix +pub fn random_matrix_3(rng: &mut R) -> CMatrix3 { + let d = Uniform::from(-10_f64..10_f64); + CMatrix3::from_fn(|_, _| Complex::new(d.sample(rng), d.sample(rng))) +} + #[cfg(test)] mod test { use rand::SeedableRng; @@ -814,7 +1017,7 @@ mod test { #[test] /// test that [`N`] is indeed what we need - fn test_constante() { + fn test_constant() { assert_eq!(N, factorial_size_for_exp() + 1); } diff --git a/src/test/integrator.rs b/src/test/integrator.rs index 1105076f..d2658d54 100644 --- a/src/test/integrator.rs +++ b/src/test/integrator.rs @@ -38,7 +38,7 @@ fn integrator() -> Result<(), Box> { let state_new = state_with_e.clone(); let state_new = state_new.simulate_to_leapfrog(&integrator, DT)?; let state_new = state_new.simulate_leap_n(&integrator, DT, 1)?; - let state_new = state_new.simulate_to_synchrone(&integrator, DT)?; + let state_new = state_new.simulate_to_synchronous(&integrator, DT)?; let state_new = state_new.simulate_sync_n(&integrator, DT, 1)?; let h2 = state_new.hamiltonian_total(); assert!((h - h2).abs() < 0.000_01_f64); @@ -58,7 +58,7 @@ fn integrator() -> Result<(), Box> { let state_new = state_with_e.clone(); let state_new = state_new.simulate_to_leapfrog(&integrator, DT)?; let state_new = state_new.simulate_leap_n(&integrator, DT, 2)?; - let state_new = state_new.simulate_to_synchrone(&integrator, DT)?; + let state_new = state_new.simulate_to_synchronous(&integrator, DT)?; let state_new = state_new.simulate_sync_n(&integrator, DT, 2)?; let h2 = state_new.hamiltonian_total(); assert!((h - h2).abs() < 0.000_01_f64); diff --git a/src/test/mod.rs b/src/test/mod.rs index f0cdc02c..b0c8bbb0 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -5,7 +5,6 @@ use std::f64; use approx::*; use na::ComplexField; use rand::SeedableRng; -use rand_distr::Distribution; use super::{ error::*, field::*, integrator::*, lattice::*, simulation::*, su3::*, thread::*, CMatrix3, @@ -20,8 +19,8 @@ const EPSILON: f64 = 0.000_000_001_f64; const SEED_RNG: u64 = 0x45_78_93_f4_4a_b0_67_f0; /// test the size of iterators -fn test_itrerator(points: usize) { - let l = LatticeCyclique::<4>::new(1_f64, points).unwrap(); +fn test_iterator(points: usize) { + let l = LatticeCyclic::<4>::new(1_f64, points).unwrap(); let link_count = l.get_links().count(); assert_eq!(link_count, 4 * points * points * points * points); assert_eq!( @@ -35,10 +34,10 @@ fn test_itrerator(points: usize) { #[test] /// test the size of iterators -fn test_itrerator_length() { - test_itrerator(2); - test_itrerator(10); - test_itrerator(26); +fn test_iterator_length() { + test_iterator(2); + test_iterator(10); + test_iterator(26); } #[allow(deprecated)] @@ -149,7 +148,7 @@ fn test_exp_basic() { #[test] #[allow(deprecated)] /// test equivalence of [`su3_exp_i`] and [`MatrixExp`] trait implementation -fn equivalece_exp_i() { +fn equivalence_exp_i() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let d = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); for i in 0..8 { @@ -171,7 +170,7 @@ fn equivalece_exp_i() { #[test] #[allow(deprecated)] /// test equivalence of [`su3_exp_r`] and [`MatrixExp`] trait implementation -fn equivalece_exp_r() { +fn equivalence_exp_r() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let d = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); for i in 0..8 { @@ -195,7 +194,7 @@ fn equivalece_exp_r() { fn create_sim() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let _simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let _simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 1_f64, 1_f64, 4, @@ -207,7 +206,7 @@ fn create_sim() { #[test] /// test creation of sim multi threaded -fn creat_sim_threaded() { +fn create_sim_threaded() { let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); let _simulation = LatticeStateEFSyncDefault::, 4>::new_random_threaded( 1_f64, @@ -223,7 +222,8 @@ fn creat_sim_threaded() { const fn delta(i: usize, j: usize) -> f64 { if i == j { 1_f64 - } else { + } + else { 0_f64 } } @@ -294,7 +294,7 @@ fn test_thread_error_zero_thread() { #[test] /// test [`run_pool_parallel_vec`] fn test_thread_vec() { - let l = LatticeCyclique::<4>::new(1_f64, 10).unwrap(); + let l = LatticeCyclic::<4>::new(1_f64, 10).unwrap(); let iter = 0..10000; let c = 5; for number_of_thread in &[1, 2, 4] { @@ -316,7 +316,7 @@ fn test_thread_vec() { #[test] fn test_thread_vec_error_zero_thread() { - let l = LatticeCyclique::<4>::new(1_f64, 10).unwrap(); + let l = LatticeCyclic::<4>::new(1_f64, 10).unwrap(); let iter = 0..10000; let result = run_pool_parallel_vec(iter.clone(), &(), &|i, _| i * i, 0, 10000, &l, &0); assert!(result.is_err()); @@ -327,7 +327,7 @@ fn test_thread_vec_error_zero_thread() { fn test_sim_hamiltonian() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 100_f64, 1_f64, 10, @@ -349,7 +349,7 @@ fn test_sim_hamiltonian() { fn test_gauss_law() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 1_f64, 1_f64, 10, @@ -379,7 +379,7 @@ fn test_gauss_law() { fn test_sim_hamiltonian_rayon() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 100_f64, 1_f64, 10, @@ -401,7 +401,7 @@ fn test_sim_hamiltonian_rayon() { fn test_gauss_law_rayon() { let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); let distribution = rand::distributions::Uniform::from(-f64::consts::PI..f64::consts::PI); - let simulation = LatticeStateEFSyncDefault::, 4>::new_deterministe( + let simulation = LatticeStateEFSyncDefault::, 4>::new_determinist( 1_f64, 1_f64, 10, @@ -427,7 +427,7 @@ fn test_gauss_law_rayon() { } #[test] -/// test that the simulatation of a cold state does not change over time +/// test that the simulation of a cold state does not change over time fn test_sim_cold() { let size = 10_f64; let number_of_pts = 10; @@ -446,7 +446,7 @@ fn test_sim_cold() { assert_eq!(sim2.e_field(), sim3.e_field()); assert_eq!(sim2.link_matrix(), sim3.link_matrix()); let sim4 = sim3 - .simulate_to_synchrone(&SymplecticEulerRayon::new(), 0.1_f64) + .simulate_to_synchronous(&SymplecticEulerRayon::new(), 0.1_f64) .unwrap(); assert_eq!(sim3.e_field(), sim4.e_field()); assert_eq!(sim3.link_matrix(), sim4.link_matrix()); @@ -567,13 +567,14 @@ fn othonomralization() { assert_eq!(orthonormalize_matrix(&m), mc); let mut rng = rand::rngs::StdRng::seed_from_u64(SEED_RNG); - let d = rand::distributions::Uniform::from(-10_f64..10_f64); + //let d = rand::distributions::Uniform::from(-10_f64..10_f64); for _ in 0_u32..100_u32 { - let m = CMatrix3::from_fn(|_, _| Complex::new(d.sample(&mut rng), d.sample(&mut rng))); + let m = random_matrix_3(&mut rng); println!("{} , {}", m, orthonormalize_matrix(&m)); if m.determinant() != Complex::from(0_f64) { test_matrix_is_su3(&orthonormalize_matrix(&m)); - } else { + } + else { assert_eq!( orthonormalize_matrix(&m).determinant(), Complex::from(0_f64) @@ -582,7 +583,7 @@ fn othonomralization() { } for _ in 0_u32..100_u32 { - let mut m = CMatrix3::from_fn(|_, _| Complex::new(d.sample(&mut rng), d.sample(&mut rng))); + let mut m = random_matrix_3(&mut rng); if m.determinant() != Complex::from(0_f64) { orthonormalize_matrix_mut(&mut m); test_matrix_is_su3(&m); @@ -601,36 +602,36 @@ fn random_su3_t() { #[test] fn lattice_init_error() { assert_eq!( - LatticeCyclique::<3>::new(0_f64, 4), + LatticeCyclic::<3>::new(0_f64, 4), Err(LatticeInitializationError::NonPositiveSize) ); assert_eq!( - LatticeCyclique::<4>::new(-1_f64, 4), + LatticeCyclic::<4>::new(-1_f64, 4), Err(LatticeInitializationError::NonPositiveSize) ); assert_eq!( - LatticeCyclique::<4>::new(f64::NAN, 4), + LatticeCyclic::<4>::new(f64::NAN, 4), Err(LatticeInitializationError::NonPositiveSize) ); assert_eq!( - LatticeCyclique::<4>::new(-0_f64, 4), + LatticeCyclic::<4>::new(-0_f64, 4), Err(LatticeInitializationError::NonPositiveSize) ); assert_eq!( - LatticeCyclique::<4>::new(f64::INFINITY, 4), + LatticeCyclic::<4>::new(f64::INFINITY, 4), Err(LatticeInitializationError::NonPositiveSize) ); assert_eq!( - LatticeCyclique::<3>::new(1_f64, 1), + LatticeCyclic::<3>::new(1_f64, 1), Err(LatticeInitializationError::DimTooSmall) ); assert_eq!( - LatticeCyclique::<3>::new(1_f64, 1), + LatticeCyclic::<3>::new(1_f64, 1), Err(LatticeInitializationError::DimTooSmall) ); - assert!(LatticeCyclique::<3>::new(1_f64, 2).is_ok()); + assert!(LatticeCyclic::<3>::new(1_f64, 2).is_ok()); assert_eq!( - LatticeCyclique::<0>::new(1_f64, 2), + LatticeCyclic::<0>::new(1_f64, 2), Err(LatticeInitializationError::ZeroDimension) ); } @@ -655,23 +656,23 @@ fn state_init_error() { 1_f64, 1_f64, 4, &d, 0, ), Err(ThreadedStateInitializationError::ThreadingError( - ThreadError::ThreadNumberIncorect + ThreadError::ThreadNumberIncorrect )) ); } #[test] fn test_length_compatible() { - let l1 = LatticeCyclique::<2>::new(1_f64, 4).unwrap(); - let l2 = LatticeCyclique::<2>::new(1_f64, 3).unwrap(); + let l1 = LatticeCyclic::<2>::new(1_f64, 4).unwrap(); + let l2 = LatticeCyclic::<2>::new(1_f64, 3).unwrap(); let link = LinkMatrix::new_cold(&l1); let e_f = EField::new_cold(&l1); - assert!(l1.has_compatible_lenght(&link, &e_f)); + assert!(l1.has_compatible_length(&link, &e_f)); let link2 = LinkMatrix::new_cold(&l2); let e_f_2 = EField::new_cold(&l2); - assert!(!l1.has_compatible_lenght(&link2, &e_f)); - assert!(!l1.has_compatible_lenght(&link2, &e_f_2)); - assert!(l2.has_compatible_lenght(&link2, &e_f_2)); + assert!(!l1.has_compatible_length(&link2, &e_f)); + assert!(!l1.has_compatible_length(&link2, &e_f_2)); + assert!(l2.has_compatible_length(&link2, &e_f_2)); } #[test] @@ -680,7 +681,7 @@ fn test_leap_frog() { let size = 1000_f64; let number_of_pts = 4; let beta = 1_f64; - let state = LatticeStateDefault::new_deterministe(size, beta, number_of_pts, &mut rng).unwrap(); + let state = LatticeStateDefault::new_determinist(size, beta, number_of_pts, &mut rng).unwrap(); println!("h_l {}", state.hamiltonian_links()); let state_hmc = LatticeStateEFSyncDefault::, 4>::new_random_e_state(state, &mut rng); diff --git a/src/thread.rs b/src/thread.rs index f1e9386b..70bdbeab 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -1,4 +1,4 @@ -//! tool for easy use of mutli threading. +//! tool for easy use of multi threading. use std::{ any::Any, @@ -17,7 +17,7 @@ use rayon::prelude::ParallelIterator; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use super::lattice::{LatticeCyclique, LatticeElementToIndex}; +use super::lattice::{LatticeCyclic, LatticeElementToIndex}; /// Multithreading error. /// @@ -27,7 +27,7 @@ use super::lattice::{LatticeCyclique, LatticeElementToIndex}; #[non_exhaustive] pub enum ThreadAnyError { /// Tried to run some jobs with 0 threads - ThreadNumberIncorect, + ThreadNumberIncorrect, /// One or more of the threads panicked. Inside the [`Box`] is the panic message. /// see [`run_pool_parallel`] example. Panic(Vec>), @@ -36,7 +36,7 @@ pub enum ThreadAnyError { impl Display for ThreadAnyError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Self::ThreadNumberIncorect => write!(f, "number of thread is incorrect"), + Self::ThreadNumberIncorrect => write!(f, "number of thread is incorrect"), Self::Panic(any) => { let n = any.len(); if n == 0 { @@ -85,7 +85,7 @@ impl Error for ThreadAnyError {} #[non_exhaustive] pub enum ThreadError { /// Tried to run some jobs with 0 threads - ThreadNumberIncorect, + ThreadNumberIncorrect, /// One of the thread panicked with the given messages. /// see [`run_pool_parallel`] example. Panic(Vec>), @@ -94,7 +94,7 @@ pub enum ThreadError { impl Display for ThreadError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Self::ThreadNumberIncorect => write!(f, "number of thread is incorrect"), + Self::ThreadNumberIncorrect => write!(f, "number of thread is incorrect"), Self::Panic(strings) => { let n = strings.len(); if n == 0 { @@ -136,7 +136,7 @@ impl From for ThreadError { #[allow(clippy::manual_map)] // clarity / false positive ? fn from(f: ThreadAnyError) -> Self { match f { - ThreadAnyError::ThreadNumberIncorect => Self::ThreadNumberIncorect, + ThreadAnyError::ThreadNumberIncorrect => Self::ThreadNumberIncorrect, ThreadAnyError::Panic(any) => Self::Panic( any.iter() .map(|element| { @@ -159,7 +159,7 @@ impl From for ThreadError { impl From for ThreadAnyError { fn from(f: ThreadError) -> Self { match f { - ThreadError::ThreadNumberIncorect => Self::ThreadNumberIncorect, + ThreadError::ThreadNumberIncorrect => Self::ThreadNumberIncorrect, ThreadError::Panic(strings) => Self::Panic( strings .iter() @@ -181,12 +181,12 @@ impl From for ThreadAnyError { /// /// The pool of job is given by `iter`. the job is given by `closure` that have the form `|key,common_data| -> Data`. /// `number_of_thread` determine the number of job done in parallel and should be greater than 0, -/// otherwise return [`ThreadAnyError::ThreadNumberIncorect`]. -/// `capacity` is used to determine the capacity of the [`HashMap`] upon initisation (see [`HashMap::with_capacity`]) +/// otherwise return [`ThreadAnyError::ThreadNumberIncorrect`]. +/// `capacity` is used to determine the capacity of the [`HashMap`] upon initiation (see [`HashMap::with_capacity`]) /// /// # Errors -/// Returns [`ThreadAnyError::ThreadNumberIncorect`] is the number of threads is 0. -/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Containt the panic message. +/// Returns [`ThreadAnyError::ThreadNumberIncorrect`] is the number of threads is 0. +/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Contains the panic message. /// /// # Example /// let us computes the value of `i^2 * c` for i in \[2,9999\] with 4 threads @@ -237,7 +237,7 @@ where Data: Send, F: Sync + Clone + Fn(&Key, &CommonData) -> Data, { - run_pool_parallel_with_initialisation_mutable( + run_pool_parallel_with_initializations_mutable( iter, common_data, &|_, key, common| closure(key, common), @@ -253,20 +253,20 @@ where /// closure_init is run once per thread and store inside a mutable data which closure can modify. /// /// # Errors -/// Returns [`ThreadAnyError::ThreadNumberIncorect`] is the number of threads is 0. -/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Containt the panick message. +/// Returns [`ThreadAnyError::ThreadNumberIncorrect`] is the number of threads is 0. +/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Contains the panic message. /// /// # Examples /// Let us create some value but we will greet the user from the threads /// ``` -/// # use lattice_qcd_rs::thread::run_pool_parallel_with_initialisation_mutable; +/// # use lattice_qcd_rs::thread::run_pool_parallel_with_initializations_mutable; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { /// let iter = 0_u128..100000_u128; /// let c = 5_u128; /// // we could have put 4 inside the closure but this demonstrate how to use common data -/// let result = run_pool_parallel_with_initialisation_mutable( +/// let result = run_pool_parallel_with_initializations_mutable( /// iter, /// &c, /// &|has_greeted: &mut bool, i, c| { @@ -290,14 +290,14 @@ where /// extern crate rand; /// extern crate rand_distr; /// use lattice_qcd_rs::field::Su3Adjoint; -/// use lattice_qcd_rs::lattice::LatticeCyclique; -/// use lattice_qcd_rs::thread::run_pool_parallel_with_initialisation_mutable; +/// use lattice_qcd_rs::lattice::LatticeCyclic; +/// use lattice_qcd_rs::thread::run_pool_parallel_with_initializations_mutable; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { -/// let l = LatticeCyclique::<4>::new(1_f64, 4)?; +/// let l = LatticeCyclic::<4>::new(1_f64, 4)?; /// let distribution = rand::distributions::Uniform::from(-1_f64..1_f64); -/// let result = run_pool_parallel_with_initialisation_mutable( +/// let result = run_pool_parallel_with_initializations_mutable( /// l.get_links(), /// &distribution, /// &|rng, _, d| Su3Adjoint::random(rng, d).to_su3(), @@ -308,9 +308,9 @@ where /// # Ok(()) /// # } /// ``` -#[allow(clippy::needless_return)] // for lisibiliy -#[allow(clippy::semicolon_if_nothing_returned)] // I actually want to retun a never in the future -pub fn run_pool_parallel_with_initialisation_mutable( +#[allow(clippy::needless_return)] // for readability +#[allow(clippy::semicolon_if_nothing_returned)] // I actually want to returns a never in the future +pub fn run_pool_parallel_with_initializations_mutable( iter: impl Iterator + Send, common_data: &CommonData, closure: &F, @@ -326,7 +326,7 @@ where FInit: Send + Clone + FnOnce() -> InitData, { if number_of_thread == 0 { - return Err(ThreadAnyError::ThreadNumberIncorect); + return Err(ThreadAnyError::ThreadNumberIncorrect); } else if number_of_thread == 1 { let mut hash_map = HashMap::::with_capacity(capacity); @@ -404,18 +404,18 @@ where /// (see [`std::vec::Vec::with_capacity`]). /// /// # Errors -/// Returns [`ThreadAnyError::ThreadNumberIncorect`] is the number of threads is 0. -/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Containt the panick message. +/// Returns [`ThreadAnyError::ThreadNumberIncorrect`] is the number of threads is 0. +/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Contains the panic message. /// /// # Example /// ``` /// use lattice_qcd_rs::field::Su3Adjoint; -/// use lattice_qcd_rs::lattice::{LatticeCyclique, LatticeElementToIndex, LatticePoint}; +/// use lattice_qcd_rs::lattice::{LatticeCyclic, LatticeElementToIndex, LatticePoint}; /// use lattice_qcd_rs::thread::run_pool_parallel_vec; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { -/// let l = LatticeCyclique::<4>::new(1_f64, 4)?; +/// let l = LatticeCyclic::<4>::new(1_f64, 4)?; /// let c = 5_usize; /// let result = run_pool_parallel_vec( /// l.get_points(), @@ -437,7 +437,7 @@ pub fn run_pool_parallel_vec( closure: &F, number_of_thread: usize, capacity: usize, - l: &LatticeCyclique, + l: &LatticeCyclic, default_data: &Data, ) -> Result, ThreadAnyError> where @@ -446,7 +446,7 @@ where Data: Send + Clone, F: Sync + Clone + Fn(&Key, &CommonData) -> Data, { - run_pool_parallel_vec_with_initialisation_mutable( + run_pool_parallel_vec_with_initializations_mutable( iter, common_data, &|_, key, common| closure(key, common), @@ -463,22 +463,22 @@ where /// run jobs in parallel. Similar to [`run_pool_parallel_vec`] but with initiation. /// /// # Errors -/// Returns [`ThreadAnyError::ThreadNumberIncorect`] is the number of threads is 0. -/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Containt the panick message. +/// Returns [`ThreadAnyError::ThreadNumberIncorrect`] is the number of threads is 0. +/// Returns [`ThreadAnyError::Panic`] if a thread panicked. Contains the panic message. /// /// # Examples /// Let us create some value but we will greet the user from the threads /// ``` -/// use lattice_qcd_rs::lattice::{LatticeCyclique, LatticeElementToIndex, LatticePoint}; -/// use lattice_qcd_rs::thread::run_pool_parallel_vec_with_initialisation_mutable; +/// use lattice_qcd_rs::lattice::{LatticeCyclic, LatticeElementToIndex, LatticePoint}; +/// use lattice_qcd_rs::thread::run_pool_parallel_vec_with_initializations_mutable; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { -/// let l = LatticeCyclique::<4>::new(1_f64, 25)?; +/// let l = LatticeCyclic::<4>::new(1_f64, 25)?; /// let iter = l.get_points(); /// let c = 5_usize; /// // we could have put 4 inside the closure but this demonstrate how to use common data -/// let result = run_pool_parallel_vec_with_initialisation_mutable( +/// let result = run_pool_parallel_vec_with_initializations_mutable( /// iter, /// &c, /// &|has_greeted: &mut bool, i: &LatticePoint<4>, c: &usize| { @@ -505,14 +505,14 @@ where /// extern crate rand_distr; /// extern crate nalgebra; /// use lattice_qcd_rs::field::Su3Adjoint; -/// use lattice_qcd_rs::lattice::LatticeCyclique; -/// use lattice_qcd_rs::thread::run_pool_parallel_vec_with_initialisation_mutable; +/// use lattice_qcd_rs::lattice::LatticeCyclic; +/// use lattice_qcd_rs::thread::run_pool_parallel_vec_with_initializations_mutable; /// # use std::error::Error; /// /// # fn main() -> Result<(), Box> { -/// let l = LatticeCyclique::<4>::new(1_f64, 4)?; +/// let l = LatticeCyclic::<4>::new(1_f64, 4)?; /// let distribution = rand::distributions::Uniform::from(-1_f64..1_f64); -/// let result = run_pool_parallel_vec_with_initialisation_mutable( +/// let result = run_pool_parallel_vec_with_initializations_mutable( /// l.get_links(), /// &distribution, /// &|rng, _, d| Su3Adjoint::random(rng, d).to_su3(), @@ -526,9 +526,9 @@ where /// # } /// ``` #[allow(clippy::too_many_arguments)] -#[allow(clippy::needless_return)] // for lisibiliy -#[allow(clippy::semicolon_if_nothing_returned)] // I actually want to retun a never in the future -pub fn run_pool_parallel_vec_with_initialisation_mutable< +#[allow(clippy::needless_return)] // for readability +#[allow(clippy::semicolon_if_nothing_returned)] // I actually want to return a never in the future +pub fn run_pool_parallel_vec_with_initializations_mutable< Key, Data, CommonData, @@ -543,7 +543,7 @@ pub fn run_pool_parallel_vec_with_initialisation_mutable< closure_init: FInit, number_of_thread: usize, capacity: usize, - l: &LatticeCyclique, + l: &LatticeCyclic, default_data: &Data, ) -> Result, ThreadAnyError> where @@ -555,7 +555,7 @@ where Key: LatticeElementToIndex, { if number_of_thread == 0 { - return Err(ThreadAnyError::ThreadNumberIncorect); + return Err(ThreadAnyError::ThreadNumberIncorrect); } else if number_of_thread == 1 { let mut vec = Vec::::with_capacity(capacity); @@ -598,7 +598,7 @@ where }); threads.push(handel); } - // we drop channel so we can proprely assert if they are closed + // we drop channel so we can properly assert if they are closed drop(result_tx); let mut vec = Vec::::with_capacity(capacity); for message in result_rx { @@ -675,7 +675,7 @@ where /// assert_eq!(result[10], 10 * 10 * c); /// ``` /// # Panic. -/// panic if the closure panic at any point during the evalutation +/// panic if the closure panic at any point during the evaluation /// ```should_panic /// # use lattice_qcd_rs::thread::run_pool_parallel_rayon; /// let iter = 0..10; @@ -708,7 +708,7 @@ mod test { #[test] fn thread_error() { assert_eq!( - format!("{}", ThreadAnyError::ThreadNumberIncorect), + format!("{}", ThreadAnyError::ThreadNumberIncorrect), "number of thread is incorrect" ); assert!( @@ -719,7 +719,7 @@ mod test { ); assert!(format!("{}", ThreadAnyError::Panic(vec![])).contains("0 thread panicked")); - assert!(ThreadAnyError::ThreadNumberIncorect.source().is_none()); + assert!(ThreadAnyError::ThreadNumberIncorrect.source().is_none()); assert!(ThreadAnyError::Panic(vec![Box::new(())]).source().is_none()); assert!( ThreadAnyError::Panic(vec![Box::new(ImplementationError::Unreachable)]) @@ -731,7 +731,7 @@ mod test { .is_none()); // ------- assert_eq!( - format!("{}", ThreadError::ThreadNumberIncorect), + format!("{}", ThreadError::ThreadNumberIncorrect), "number of thread is incorrect" ); assert!(format!("{}", ThreadError::Panic(vec![None])).contains("a thread panicked")); @@ -743,7 +743,7 @@ mod test { .contains("message 1")); assert!(format!("{}", ThreadError::Panic(vec![])).contains("0 thread panicked")); - assert!(ThreadError::ThreadNumberIncorect.source().is_none()); + assert!(ThreadError::ThreadNumberIncorrect.source().is_none()); assert!(ThreadError::Panic(vec![None]).source().is_none()); assert!(ThreadError::Panic(vec![Some("".to_string())]) .source() @@ -767,10 +767,10 @@ mod test { assert_eq!(ThreadError::from(error), error3); assert_eq!(ThreadAnyError::from(error3).to_string(), error2.to_string()); - let error = ThreadAnyError::ThreadNumberIncorect; - let error2 = ThreadError::ThreadNumberIncorect; + let error = ThreadAnyError::ThreadNumberIncorrect; + let error2 = ThreadError::ThreadNumberIncorrect; assert_eq!(ThreadError::from(error), error2); - let error = ThreadAnyError::ThreadNumberIncorect; + let error = ThreadAnyError::ThreadNumberIncorrect; assert_eq!(ThreadAnyError::from(error2).to_string(), error.to_string()); } } diff --git a/src/utils.rs b/src/utils.rs index dec86e66..d2d93864 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,7 +46,7 @@ pub const fn factorial(n: usize) -> FactorialNumber { /// Dynamical size factorial storage. /// -/// Used as a lazy cache for factoral number. This is not actually used and might be removed later. +/// Used as a lazy cache for factorial number. This is not actually used and might be removed later. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FactorialStorageDyn { data: Vec, @@ -141,9 +141,9 @@ impl FactorialStorageDyn { #[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub enum Sign { - /// Stricly negative number (non zero) + /// Strictly negative number (non zero) Negative, - /// Stricly positive number ( non zero) + /// Strictly positive number ( non zero) Positive, /// Zero (or very close to zero) Zero, @@ -164,7 +164,6 @@ impl Sign { /// If the value is very close to zero but not quite the sing will nonetheless be [`Sign::Zero`]. /// If f is NaN the sing will be [`Sign::Zero`]. pub fn sign_f64(f: f64) -> Self { - // TODO manage NaN if abs_diff_eq!(f, 0_f64) || f.is_nan() { Sign::Zero } @@ -199,7 +198,7 @@ impl Sign { } } - /// Retuns the sign of `a - b`, with a and b are usize + /// Returns the sign of `a - b`, where `a` and `b` are usize #[allow(clippy::comparison_chain)] pub const fn sign_from_diff(a: usize, b: usize) -> Self { if a == b {