castep-cell-io 0.2.11

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

use metals_method::{DensityMixing, Edft, MetalsMethod};

use super::{OptionDisplay, ParamSectionDisplay};

mod metals_method;
/// Electronic minimization parameters
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum ElectroMinParam {
    EFERMI_TOL,
    ELEC_CONVERGENCE_WIN,
    ELEC_DUMP_FILE,
    ELEC_EIGENVALUE_TOL,
    ELEC_ENERGY_TOL(f64),
    ELEC_RESTORE_FILE,
    ELECTRONIC_MINIMIZER,
    FIX_OCCUPANCY(bool),
    MAX_CG_STEPS,
    MAX_SCF_CYCLES(u32),
    MAX_SD_STEPS,
    METALS_METHOD(MetalsMethod),
    NUM_DUMP_CYCLES(u32),
    SMEARING_SCHEME,
    SMEARING_WIDTH(f64),
    SPIN_FIX(u32),
}

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

impl ElectroMinParamSection {
    pub fn new(params: Vec<ElectroMinParam>) -> Self {
        Self { params }
    }
    pub fn with_edft() -> Self {
        Self::new(vec![
            ElectroMinParam::ELEC_ENERGY_TOL(1e-5),
            ElectroMinParam::FIX_OCCUPANCY(false),
            ElectroMinParam::METALS_METHOD(MetalsMethod::Edft(Edft::default())),
            ElectroMinParam::MAX_SCF_CYCLES(6000),
            ElectroMinParam::SMEARING_WIDTH(0.1_f64),
            ElectroMinParam::SPIN_FIX(6),
            ElectroMinParam::NUM_DUMP_CYCLES(0),
        ])
    }
}

impl Default for ElectroMinParamSection {
    fn default() -> Self {
        Self::new(vec![
            ElectroMinParam::ELEC_ENERGY_TOL(1e-5),
            ElectroMinParam::FIX_OCCUPANCY(false),
            ElectroMinParam::METALS_METHOD(MetalsMethod::Dm(DensityMixing::default())),
            ElectroMinParam::MAX_SCF_CYCLES(6000),
            ElectroMinParam::SMEARING_WIDTH(0.1_f64),
            ElectroMinParam::SPIN_FIX(6),
            ElectroMinParam::NUM_DUMP_CYCLES(0),
        ])
    }
}

impl OptionDisplay for ElectroMinParam {
    fn tag(&self) -> String {
        match self {
            ElectroMinParam::EFERMI_TOL => "efermi_tol".to_string(),
            ElectroMinParam::ELEC_CONVERGENCE_WIN => "elec_convergence_win".to_string(),
            ElectroMinParam::ELEC_DUMP_FILE => "elec_dump_file".to_string(),
            ElectroMinParam::ELEC_EIGENVALUE_TOL => "elec_eigenvalue_tol".to_string(),
            ElectroMinParam::ELEC_ENERGY_TOL(_) => "elec_energy_tol".to_string(),
            ElectroMinParam::ELEC_RESTORE_FILE => "elec_restore_file".to_string(),
            ElectroMinParam::ELECTRONIC_MINIMIZER => "electronic_minimizer".to_string(),
            ElectroMinParam::FIX_OCCUPANCY(_) => "fix_occupancy".to_string(),
            ElectroMinParam::MAX_CG_STEPS => "max_cg_steps".to_string(),
            ElectroMinParam::MAX_SCF_CYCLES(_) => "max_scf_cycles".to_string(),
            ElectroMinParam::MAX_SD_STEPS => "max_sd_steps".to_string(),
            ElectroMinParam::METALS_METHOD(_) => "metals_method".to_string(),
            ElectroMinParam::NUM_DUMP_CYCLES(_) => "num_dump_cycles".to_string(),
            ElectroMinParam::SMEARING_SCHEME => "smearing_scheme".to_string(),
            ElectroMinParam::SMEARING_WIDTH(_) => "smearing_width".to_string(),
            ElectroMinParam::SPIN_FIX(_) => "spin_fix".to_string(),
        }
    }

    fn value(&self) -> String {
        match self {
            ElectroMinParam::EFERMI_TOL => todo!(),
            ElectroMinParam::ELEC_CONVERGENCE_WIN => todo!(),
            ElectroMinParam::ELEC_DUMP_FILE => todo!(),
            ElectroMinParam::ELEC_EIGENVALUE_TOL => todo!(),
            ElectroMinParam::ELEC_ENERGY_TOL(f) => format!("{f:18.15e}"),
            ElectroMinParam::ELEC_RESTORE_FILE => todo!(),
            ElectroMinParam::ELECTRONIC_MINIMIZER => todo!(),
            ElectroMinParam::FIX_OCCUPANCY(b) => format!("{b}"),
            ElectroMinParam::MAX_CG_STEPS => todo!(),
            ElectroMinParam::MAX_SCF_CYCLES(i) => format!("{i:>7}"),
            ElectroMinParam::MAX_SD_STEPS => todo!(),
            ElectroMinParam::METALS_METHOD(mm) => format!("{mm}"),
            ElectroMinParam::NUM_DUMP_CYCLES(i) => format!("{i:>3}"),
            ElectroMinParam::SMEARING_SCHEME => todo!(),
            ElectroMinParam::SMEARING_WIDTH(f) => format!("{f:24.15}"),
            ElectroMinParam::SPIN_FIX(i) => format!("{i}"),
        }
    }
}

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

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

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

#[cfg(test)]
mod test {

    use super::ElectroMinParamSection;

    #[test]
    fn test_em_param() {
        let dm_param = ElectroMinParamSection::default();
        println!("{dm_param}");
        let edft_param = ElectroMinParamSection::with_edft();
        println!("{edft_param}");
    }
}