Skip to content

Commit

Permalink
start working on EField builder
Browse files Browse the repository at this point in the history
  • Loading branch information
ABouttefeux committed Mar 3, 2022
1 parent adcbc2c commit da3ab61
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 21 deletions.
22 changes: 22 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! builder utility

use std::num::NonZeroUsize;

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

/// Type of generation
#[non_exhaustive]
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum GenType<'rng, Rng: rand::Rng + ?Sized> {
/// Cold generation all ellements are set to the default
Cold,
/// Random deterministe
#[cfg_attr(feature = "serde-serialize", serde(skip_deserializing))]
HotDeterministe(&'rng mut Rng),
/// Random deterministe but own the RNG (for instance the result of `clone`)
HotDeterministeOwned(Box<Rng>),
/// Random threaded (non deterministe)
HotThreaded(NonZeroUsize),
}
2 changes: 2 additions & 0 deletions src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ use super::{

mod link_matrix_builder;
pub use link_matrix_builder::*;
mod e_field_builder;
pub use e_field_builder::*;

/// Adjoint representation of SU(3), it is su(3) (i.e. the lie algebra).
/// See [`su3::GENERATORS`] to view the order of generators.
Expand Down
75 changes: 75 additions & 0 deletions src/field/e_field_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::borrow::Cow;
use std::fmt::Debug;
use std::num::NonZeroUsize;

use rand::distributions::Distribution;
use rand_distr::Normal;
#[cfg(feature = "serde-serialize")]
use serde::Serialize;

use super::EField;
use crate::builder::GenType;
use crate::lattice::LatticeCyclique;
use crate::{CMatrix3, Real};

#[derive(Debug, Clone)]
enum DistributionForBuilder<'dis, Dis: Distribution<Real> + ?Sized> {
Default(Normal<Real>),
Given(&'dis Dis), // TODO box dyn
}

impl<'d, Dis: Distribution<Real> + ?Sized> Default for DistributionForBuilder<'d, Dis> {
fn default() -> Self {
Self::Default(Normal::new(0_f64, 0.5_f64).unwrap())
}
}

#[derive(Clone, Debug)]
pub struct EFieldProceduralBuilder<
'rng,
'lat,
'dis,
Rng: rand::Rng + ?Sized,
Dis: Distribution<Real> + ToOwned + ?Sized,
const D: usize,
> {
gen_type: GenType<'rng, Rng>,
lattice: Cow<'lat, LatticeCyclique<D>>,
distribution: DistributionForBuilder<'dis, Dis>,
}

/*
impl<'r, 'l, 'd, Rng: rand::Rng + ?Sized, Dis, const D: usize> Debug
for EFieldProceduralBuilder<'r, 'l, 'd, Rng, Dis, D>
where
Dis: Distribution<Real> + ?Sized + ToOwned + Debug,
Rng: Debug,
Dis::Owned: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EFieldProceduralBuilder")
.field("gen_type", &self.gen_type)
.field("lattice", &self.lattice)
.field("distribution", &self.distribution)
.finish()
}
}
*/

impl<
'rng,
'lat,
'dis,
Rng: rand::Rng + ?Sized,
Dis: Distribution<Real> + ToOwned + ?Sized,
const D: usize,
> EFieldProceduralBuilder<'rng, 'lat, 'dis, Rng, Dis, D>
{
pub fn new(lattice: impl Into<Cow<'lat, LatticeCyclique<D>>>) -> Self {
Self {
gen_type: GenType::Cold,
lattice: lattice.into(),
distribution: DistributionForBuilder::default(),
}
}
}
146 changes: 125 additions & 21 deletions src/field/link_matrix_builder.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::num::NonZeroUsize;

#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};
use serde::Serialize;

use super::LinkMatrix;
use crate::builder::GenType;
use crate::lattice::LatticeCyclique;
use crate::CMatrix3;

Expand All @@ -17,22 +18,6 @@ enum LinkMatrixBuilderType<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize>
Data(Vec<CMatrix3>),
}

/// Type of generation
#[non_exhaustive]
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
enum GenType<'rng, Rng: rand::Rng + ?Sized> {
/// Cold generation all ellements are set to the default
Cold,
/// Random deterministe
#[cfg_attr(feature = "serde-serialize", serde(skip_deserializing))]
HotDeterministe(&'rng mut Rng),
/// Random deterministe but own the RNG (for instance the result of `clone`)
HotDeterministeOwned(Box<Rng>),
/// Random threaded (non deterministe)
HotThreaded(NonZeroUsize),
}

impl<'rng, Rng: rand::Rng + Clone + ?Sized> Clone for GenType<'rng, Rng> {
fn clone(&self) -> Self {
match self {
Expand Down Expand Up @@ -67,25 +52,93 @@ impl<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize>
}
}

/// Consuming [`LinkMatrix`] builder.
/// There is two way to startt the builder, [`LinkMatrixBuilder::new_from_data`]
/// [`LinkMatrixBuilder::new_procedural`].
///
/// The first one juste move the data given in the
/// [`LinkMatrix`] and does not require another configuration.
///
/// The seconde one will build a [`LinkMatrix`] procedurally and accept three configurations.
/// [`LinkMatrixBuilder::set_cold`] that generate a configuration with only indentity matrices.
/// [`LinkMatrixBuilder::set_hot_deterministe`] choose randomly every link matrices with a SU(3)
/// matrix unfiformly distributed in a reproductible way
/// [`LinkMatrixBuilder::set_hot_threaded`] also chooses random matrices as above but does it
/// with multiple thread and is not deterministe.
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize))]
pub struct LinkMatrixBuilder<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize> {
builder_type: LinkMatrixBuilderType<'rng, 'lat, Rng, D>,
}

impl<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize> LinkMatrixBuilder<'rng, 'lat, Rng, D> {
/// This method take an array of data as the base contruction of [`LinkMatrix`].
///
/// Using this methode has no other configuration and can be direcly build.
/// It is equivalent to [`LinkMatrix::new`]
/// # Example
/// ```
/// use lattice_qcd_rs::field::LinkMatrixBuilder;
/// use lattice_qcd_rs::CMatrix3;
/// use rand::rngs::ThreadRng;
///
/// let vec = vec![CMatrix3::identity(); 16];
/// let links = LinkMatrixBuilder::<'_, '_, ThreadRng, 4>::new_from_data(vec.clone()).build();
/// assert_eq!(&vec, links.as_vec());
/// ```
pub fn new_from_data(data: Vec<CMatrix3>) -> Self {
Self {
builder_type: LinkMatrixBuilderType::Data(data),
}
}

pub fn new_generated(l: &'lat LatticeCyclique<D>) -> Self {
/// Initialize the builder to use procedural generation.
///
/// By default the generation type is set to cold.
///
/// # Example
/// ```
/// use lattice_qcd_rs::field::LinkMatrixBuilder;
/// use lattice_qcd_rs::lattice::LatticeCyclique;
/// use lattice_qcd_rs::CMatrix3;
/// use rand::rngs::ThreadRng;
/// # use std::error::Error;
///
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let lat = LatticeCyclique::<3>::new(1_f64, 4)?;
/// let links = LinkMatrixBuilder::<'_, '_, ThreadRng, 3>::new_procedural(&lat).build();
/// assert!(lat.has_compatible_lenght_links(&links));
/// # Ok(())
/// # }
/// ```
pub fn new_procedural(l: &'lat LatticeCyclique<D>) -> Self {
Self {
builder_type: LinkMatrixBuilderType::Generated(l, GenType::Cold),
}
}

/// Change the methode to a cold generation, i.e. all links are set to the identity.
/// Does not affect generactor build with [`LinkMatrixBuilder::new_from_data`].
///
/// # Example
/// ```
/// use lattice_qcd_rs::field::LinkMatrixBuilder;
/// use lattice_qcd_rs::lattice::LatticeCyclique;
/// use lattice_qcd_rs::CMatrix3;
/// use rand::rngs::ThreadRng;
/// # use std::error::Error;
///
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let lat = LatticeCyclique::<3>::new(1_f64, 4)?;
/// let links = LinkMatrixBuilder::<'_, '_, ThreadRng, 3>::new_procedural(&lat)
/// .set_cold()
/// .build();
/// for m in &links {
/// assert_eq!(m, &CMatrix3::identity());
/// }
/// # Ok(())
/// # }
/// ```
pub fn set_cold(mut self) -> Self {
match self.builder_type {
LinkMatrixBuilderType::Data(_) => {}
Expand All @@ -96,6 +149,32 @@ impl<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize> LinkMatrixBuilder<'rng
self
}

/// Change the methode to a hot determinist generation, i.e. all links generated randomly in a single thread.
/// Does not affect generactor build with [`LinkMatrixBuilder::new_from_data`].
///
/// # Example
/// ```
/// use lattice_qcd_rs::field::LinkMatrixBuilder;
/// use lattice_qcd_rs::lattice::LatticeCyclique;
/// use lattice_qcd_rs::CMatrix3;
/// use rand::rngs::StdRng;
/// use rand::SeedableRng;
/// # use std::error::Error;
///
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let mut rng = StdRng::seed_from_u64(0); // change the seed
/// let lat = LatticeCyclique::<3>::new(1_f64, 4)?;
/// let links = LinkMatrixBuilder::<'_, '_, StdRng, 3>::new_procedural(&lat)
/// .set_hot_deterministe(&mut rng)
/// .build();
/// let mut rng_2 = StdRng::seed_from_u64(0); // same seed as before
/// let links_2 = LinkMatrixBuilder::<'_, '_, StdRng, 3>::new_procedural(&lat)
/// .set_hot_deterministe(&mut rng_2)
/// .build();
/// assert_eq!(links, links_2);
/// # Ok(())
/// # }
/// ```
pub fn set_hot_deterministe(mut self, rng: &'rng mut Rng) -> Self {
match self.builder_type {
LinkMatrixBuilderType::Data(_) => {}
Expand All @@ -107,6 +186,30 @@ impl<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize> LinkMatrixBuilder<'rng
self
}

/// Change the methode to a hot determinist generation, i.e. all links generated randomly using multiple threads.
/// Does not affect generactor build with [`LinkMatrixBuilder::new_from_data`].
///
/// # Example
/// ```
/// use std::num::NonZeroUsize;
///
/// use lattice_qcd_rs::error::ImplementationError;
/// use lattice_qcd_rs::field::LinkMatrixBuilder;
/// use lattice_qcd_rs::lattice::LatticeCyclique;
/// use lattice_qcd_rs::CMatrix3;
/// use rand::rngs::ThreadRng;
/// # use std::error::Error;
///
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let lat = LatticeCyclique::<3>::new(1_f64, 4)?;
/// let number_of_threads =
/// NonZeroUsize::new(4).ok_or(ImplementationError::OptionWithUnexpectedNone)?;
/// let links = LinkMatrixBuilder::<'_, '_, ThreadRng, 3>::new_procedural(&lat)
/// .set_hot_threaded(number_of_threads)
/// .build();
/// # Ok(())
/// # }
/// ```
pub fn set_hot_threaded(mut self, number_of_threads: NonZeroUsize) -> Self {
match self.builder_type {
LinkMatrixBuilderType::Data(_) => {}
Expand All @@ -118,6 +221,7 @@ impl<'rng, 'lat, Rng: rand::Rng + ?Sized, const D: usize> LinkMatrixBuilder<'rng
self
}

/// Therminal methode to build the [`LinkMatrix`]
pub fn build(self) -> LinkMatrix {
self.builder_type.into_link_matrix()
}
Expand Down Expand Up @@ -155,17 +259,17 @@ mod test {
#[test]
fn builder() -> Result<(), LatticeInitializationError> {
let lattice = LatticeCyclique::<3>::new(1_f64, 10)?;
let m = LinkMatrixBuilder::<'_, '_, rand::rngs::ThreadRng, 3>::new_generated(&lattice)
let m = LinkMatrixBuilder::<'_, '_, rand::rngs::ThreadRng, 3>::new_procedural(&lattice)
.set_cold()
.build();
assert_eq!(m, LinkMatrix::new_cold(&lattice));

let mut rng = StdRng::seed_from_u64(SEED_RNG);
let builder = LinkMatrixBuilder::<'_, '_, _, 3>::new_generated(&lattice)
let builder = LinkMatrixBuilder::<'_, '_, _, 3>::new_procedural(&lattice)
.set_hot_deterministe(&mut rng);
let m = builder.clone().build();
assert_eq!(m, builder.build());
let _ = LinkMatrixBuilder::<'_, '_, rand::rngs::ThreadRng, 3>::new_generated(&lattice)
let _ = LinkMatrixBuilder::<'_, '_, rand::rngs::ThreadRng, 3>::new_procedural(&lattice)
.set_hot_threaded(NonZeroUsize::new(rayon::current_num_threads().min(1)).unwrap())
.build();
assert!(LinkMatrixBuilder::<'_, '_, _, 3>::new_from_data(vec![])
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ pub use rand_distr::Distribution;

#[macro_use]
mod macro_def;
pub(crate) mod builder;
pub mod dim;
pub mod error;
pub mod field;
Expand Down

0 comments on commit da3ab61

Please sign in to comment.