1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

//! The `spglib` crate provides a Rust-y wrapper to [spglib](https://atztogo.github.io/spglib/), a C library for finding and handling crystal symmetries.

pub mod cell;
pub mod dataset;
mod internal;
pub mod spacegroup;
use spglib_sys as ffi;
use std::error;
use std::fmt;
use std::os::raw::c_int;

/// Returns the major version of spglib
pub fn major_version() -> i32 {
    unsafe { ffi::spg_get_major_version() }
}

/// Returns the minor version of spglib
pub fn minor_version() -> i32 {
    unsafe { ffi::spg_get_minor_version() }
}

/// Returns the micro version of spglib
pub fn micro_version() -> i32 {
    unsafe { ffi::spg_get_micro_version() }
}

/// Returns the hall number for a given set of symmetry operations
///
/// # Examples
///
/// Get the hall number for a BCC cell in a roundabout way
///
/// ```
/// use spglib as spg;
/// # use spglib::cell::Cell;
/// # use spglib::dataset::Dataset;
/// # let lattice = [[4., 0., 0.], [0., 4., 0.], [0., 0., 4.]];
/// # let positions = &[[0., 0., 0.], [0.5, 0.5, 0.5]];
/// # let types = &[1, 1];
/// # let mut bcc_cell = Cell::new(lattice, positions, types);
/// let dataset = Dataset::new(&mut bcc_cell, 1e-5);
/// let mut rotations = dataset.rotations.clone();
/// let mut translations = dataset.translations.clone();
/// let hall_number =
///     spg::hall_number_from_symmetry(&mut rotations, &mut translations, 1e-5);
/// assert_eq!(hall_number, dataset.hall_number);
/// ```
pub fn hall_number_from_symmetry(
    rotations: &mut [[[i32; 3]; 3]],
    translations: &mut [[f64; 3]],
    symprec: f64,
) -> i32 {
    let n_operations = rotations.len();
    unsafe {
        ffi::spg_get_hall_number_from_symmetry(
            rotations.as_ptr() as *mut [[c_int; 3]; 3],
            translations.as_ptr() as *mut [f64; 3],
            n_operations as c_int,
            symprec,
        )
    }
}

#[derive(Debug, Clone)]
/// Error raised when a cell cannot be standardized
pub struct StandardizeError;

impl fmt::Display for StandardizeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to standardize the cell")
    }
}

impl error::Error for StandardizeError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
}

#[derive(Debug, Clone)]
/// Error raised when a cell cannot be reduced with the Delaunay reduction scheme
pub struct DelaunayReduceError;

impl fmt::Display for DelaunayReduceError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to reduce the cell")
    }
}

impl error::Error for DelaunayReduceError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
}

#[derive(Debug, Clone)]
/// Error raised when a cell cannot be reduced with the Niggli reduction scheme
pub struct NiggliReduceError;

impl fmt::Display for NiggliReduceError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to reduce the cell")
    }
}

impl error::Error for NiggliReduceError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
}

#[cfg(test)]
mod tests {
    use crate as spg;
    use crate::dataset::Dataset;
    use crate::internal::rutile_cell;
    #[test]
    fn hall_number_from_symmetry() {
        let mut cell = rutile_cell();
        let symprec = 1e-5;
        let dataset = Dataset::new(&mut cell, symprec);
        let mut rotations = dataset.rotations.clone();
        let mut translations = dataset.translations.clone();
        let hall_number =
            spg::hall_number_from_symmetry(&mut rotations, &mut translations, symprec);
        assert_eq!(hall_number, dataset.hall_number);
    }
}