castep-cell-io 0.2.12

A crate helping to parse, edit and save `castep` input file format `.cell`
Documentation
use std::fmt::Display;

use super::{OptionDisplay, ParamSectionDisplay};

#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
pub enum GeomOptParam {
    GEOM_CONVERGENCE_WIN(u32),
    GEOM_DISP_TOL(f64),
    GEOM_ENERGY_TOL(f64),
    GEOM_FORCE_TOL(f64),
    GEOM_FREQUENCY_EST(f64),
    GEOM_MAX_ITER(u32),
    GEOM_METHOD(GeomMethod),
    GEOM_MODULUS_EST(f64),
    GEOM_PRECONDITIONER(GeomPreConditioner),
    GEOM_SPIN_FIX(u32),
    GEOM_STRESS_TOL(f64),
}

#[derive(Debug, Clone)]
pub struct GeomOptParamSection {
    params: Vec<GeomOptParam>,
}

impl GeomOptParamSection {
    pub fn new(params: Vec<GeomOptParam>) -> Self {
        Self { params }
    }

    pub fn params(&self) -> &[GeomOptParam] {
        &self.params
    }
}

impl Default for GeomOptParamSection {
    fn default() -> Self {
        Self::new(vec![
            GeomOptParam::GEOM_ENERGY_TOL(5e-5),
            GeomOptParam::GEOM_FORCE_TOL(0.1),
            GeomOptParam::GEOM_STRESS_TOL(0.2),
            GeomOptParam::GEOM_DISP_TOL(0.005),
            GeomOptParam::GEOM_MAX_ITER(6000),
            GeomOptParam::GEOM_METHOD(GeomMethod::default()),
        ])
    }
}

impl OptionDisplay for GeomOptParam {
    fn tag(&self) -> String {
        match self {
            GeomOptParam::GEOM_CONVERGENCE_WIN(_) => "geom_convergence_win".to_string(),
            GeomOptParam::GEOM_DISP_TOL(_) => "geom_disp_tol".to_string(),
            GeomOptParam::GEOM_ENERGY_TOL(_) => "geom_energy_tol".to_string(),
            GeomOptParam::GEOM_FORCE_TOL(_) => "geom_force_tol".to_string(),
            GeomOptParam::GEOM_FREQUENCY_EST(_) => "geom_frequency_est".to_string(),
            GeomOptParam::GEOM_MAX_ITER(_) => "geom_max_iter".to_string(),
            GeomOptParam::GEOM_METHOD(_) => "geom_method".to_string(),
            GeomOptParam::GEOM_MODULUS_EST(_) => "geom_modulus_est".to_string(),
            GeomOptParam::GEOM_PRECONDITIONER(_) => "geom_preconditioner".to_string(),
            GeomOptParam::GEOM_SPIN_FIX(_) => "geom_spin_fix".to_string(),
            GeomOptParam::GEOM_STRESS_TOL(_) => "geom_stress_tol".to_string(),
        }
    }

    fn value(&self) -> String {
        match self {
            GeomOptParam::GEOM_CONVERGENCE_WIN(u) => format!("{u}"),
            GeomOptParam::GEOM_DISP_TOL(f) => format!("{f:24.15}"),
            GeomOptParam::GEOM_ENERGY_TOL(f) => format!("{f:24.15e}"),
            GeomOptParam::GEOM_FORCE_TOL(f) => format!("{f:24.15}"),
            GeomOptParam::GEOM_FREQUENCY_EST(f) => format!("{f:24.15}"),
            GeomOptParam::GEOM_MAX_ITER(u) => format!("{u}"),
            GeomOptParam::GEOM_METHOD(gm) => format!("{gm}"),
            GeomOptParam::GEOM_MODULUS_EST(f) => format!("{f:24.15}"),
            GeomOptParam::GEOM_PRECONDITIONER(gp) => format!("{gp}"),
            GeomOptParam::GEOM_SPIN_FIX(u) => format!("{u}"),
            GeomOptParam::GEOM_STRESS_TOL(f) => format!("{f:24.15}"),
        }
    }
}

impl Display for GeomOptParam {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.output())
    }
}

impl ParamSectionDisplay for GeomOptParamSection {
    fn options(&self) -> &[impl Display] {
        self.params()
    }
}

impl Display for GeomOptParamSection {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.section_content())
    }
}

#[derive(Debug, Clone, Copy, Default)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
pub enum GeomMethod {
    #[default]
    BFGS,
    LBFGS,
    Delocalized,
    DampedMD,
    TPSD,
}

impl Display for GeomMethod {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            GeomMethod::BFGS => f.write_str("BFGS"),
            GeomMethod::LBFGS => f.write_str("LBFGS"),
            GeomMethod::Delocalized => f.write_str("Delocalized"),
            GeomMethod::DampedMD => f.write_str("DampedMD"),
            GeomMethod::TPSD => f.write_str("TPSD"),
        }
    }
}

#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
pub enum GeomPreConditioner {
    ID,
    EXP,
    FF,
}

impl Display for GeomPreConditioner {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            GeomPreConditioner::ID => f.write_str("ID"),
            GeomPreConditioner::EXP => f.write_str("EXP"),
            GeomPreConditioner::FF => f.write_str("FF"),
        }
    }
}

#[cfg(test)]
mod test {
    use super::GeomOptParamSection;

    #[test]
    fn test_geom_pm() {
        let pm = GeomOptParamSection::default();
        println!("{pm}");
    }
}