spglib 1.15.1

Rust bindings to spglib.
Documentation
//! Representation of a bounded atomic structure.

use std::os::raw::c_int;

use spglib_sys as ffi;

use crate::error::SpglibError;

/// Atomic structure with lattice bounds.
#[derive(Clone, Debug)]
pub struct Cell {
    /// Lattice vectors.
    pub lattice: [[f64; 3]; 3],
    /// Position of each atom.
    pub positions: Vec<[f64; 3]>,
    /// Type of each atom.
    pub types: Vec<i32>,
}

impl Cell {
    /// Returns a new cell.
    pub fn new(lattice: &[[f64; 3]; 3], positions: &[[f64; 3]], types: &[i32]) -> Cell {
        let lattice = *lattice;
        let positions = Vec::from(positions);
        let types = Vec::from(types);
        Cell {
            lattice,
            positions,
            types,
        }
    }

    /// Standardizes the cell with a symmetry search.
    /// Refer to the full documentation of the implementation [here](https://spglib.github.io/spglib/api.html#spg-standardize-cell).
    ///
    /// # Example
    ///
    /// Standardize a BCC cell.
    ///
    /// ```
    /// use spglib::cell::Cell;
    ///
    /// let lattice = [
    ///     [4.0, 0.0, 0.0],
    ///     [0.0, 4.0, 0.0],
    ///     [0.0, 0.0, 4.0]
    /// ];
    /// let positions = [
    ///     [0.0, 0.0, 0.0],
    ///     [0.5, 0.5, 0.5]
    /// ];
    /// let types = [1, 1];
    /// let mut cell = Cell::new(&lattice, &positions, &types);
    /// cell.standardize(true, false, 1.0e-6).unwrap();
    /// assert_eq!(
    ///     cell.lattice,
    ///     [
    ///         [-2.0, 2.0, 2.0],
    ///         [2.0, -2.0, 2.0],
    ///         [2.0, 2.0, -2.0]
    ///     ]
    /// );
    /// ```
    pub fn standardize(
        &mut self,
        to_primitive: bool,
        no_idealize: bool,
        symprec: f64,
    ) -> Result<(), SpglibError> {
        let to_primitive = if to_primitive { 1 } else { 0 };
        let no_idealize = if no_idealize { 1 } else { 0 };
        let res = unsafe {
            ffi::spg_standardize_cell(
                self.lattice.as_ptr() as *mut [f64; 3],
                self.positions.as_ptr() as *mut [f64; 3],
                self.types.as_ptr() as *mut c_int,
                self.positions.len() as c_int,
                to_primitive,
                no_idealize,
                symprec,
            )
        };
        if res == 0 {
            return Err(SpglibError::CellStandardizationFailed);
        }
        Ok(())
    }

    /// Applies a Delaunay reduction to the cell.
    /// Refer to the full documentation of the implementation [here](https://spglib.github.io/spglib/api.html#spg-delaunay-reduce).
    pub fn delaunay_reduce(&mut self, eps: f64) -> Result<(), SpglibError> {
        let res = unsafe { ffi::spg_delaunay_reduce(self.lattice.as_ptr() as *mut [f64; 3], eps) };
        if res == 0 {
            return Err(SpglibError::DelaunayFailed);
        }
        Ok(())
    }

    /// Applies a Niggli reduction to the cell.
    /// Refer to the full documentation of the implementation [here](https://spglib.github.io/spglib/api.html#spg-niggli-reduce).
    pub fn niggli_reduce(&mut self, eps: f64) -> Result<(), SpglibError> {
        let res = unsafe { ffi::spg_niggli_reduce(self.lattice.as_ptr() as *mut [f64; 3], eps) };
        if res == 0 {
            return Err(SpglibError::NiggliFailed);
        }
        Ok(())
    }

    /// This method is not yet implemented.
    pub fn ir_reciprocal_mesh(
        &self,
        mesh: (i32, i32, i32),
        shift: (bool, bool, bool),
    ) -> Result<(), SpglibError> {
        unimplemented!()
    }
}