castep_param_io/param/pseudopotentials/
mod.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::Display;
3
4use crate::param::KeywordDisplay;
5
6use derive_builder::Builder;
7pub use pspot_beta_phi_type::PSPotBetaPhiType;
8pub use pspot_nonlocal_type::PSPotNonlocalType;
9pub use relativistic_treatment::RelativisticTreatment;
10
11mod pspot_beta_phi_type;
12mod pspot_nonlocal_type;
13mod relativistic_treatment;
14
15#[derive(
16    Debug,
17    Clone,
18    Copy,
19    Hash,
20    Serialize,
21    Deserialize,
22    PartialEq,
23    Eq,
24    PartialOrd,
25    Ord,
26    Builder,
27    Default,
28)]
29#[builder(
30    setter(into, strip_option),
31    default,
32    build_fn(validate = "Self::validate")
33)]
34pub struct Pseudopotentials {
35    pub pspot_beta_phi_type: Option<PSPotBetaPhiType>,
36    pub pspot_nonlocal_type: Option<PSPotNonlocalType>,
37    pub relativistic_treatment: Option<RelativisticTreatment>,
38}
39
40impl Display for Pseudopotentials {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        let output = [
43            self.pspot_beta_phi_type.map(|v| v.output()),
44            self.pspot_nonlocal_type.map(|v| v.output()),
45            self.relativistic_treatment.map(|v| v.output()),
46        ]
47        .into_iter()
48        .flatten()
49        .collect::<Vec<String>>()
50        .join("\n");
51        write!(f, "{}", output)
52    }
53}
54impl PseudopotentialsBuilder {
55    fn validate(builder: &PseudopotentialsBuilder) -> Result<(), String> {
56        if let Some(Some(non)) = builder.pspot_nonlocal_type {
57            match non {
58            PSPotNonlocalType::Reciprocal => match builder.pspot_beta_phi_type {
59                Some(Some(b)) => match b {
60                            PSPotBetaPhiType::Reciprocal => Ok(()),
61                            PSPotBetaPhiType::Real => Err("The `pspot_beta_phi_type` can only take `REAL` if `pspot_nonlocal_type` is also `REAL`".to_string())
62                        },
63                Some(None) => Ok(()),
64                None => Ok(()),
65                },
66            PSPotNonlocalType::Real => Ok(()),
67        }
68        } else {
69            Ok(())
70        }
71    }
72}
73
74#[cfg(test)]
75mod test {
76    use crate::param::pseudopotentials::{
77        PSPotBetaPhiType, PSPotNonlocalType, RelativisticTreatment,
78    };
79
80    use super::PseudopotentialsBuilder;
81
82    #[test]
83    fn pseudopotentials() {
84        let p = PseudopotentialsBuilder::default()
85            .pspot_beta_phi_type(PSPotBetaPhiType::Real)
86            .pspot_nonlocal_type(PSPotNonlocalType::Real)
87            .relativistic_treatment(RelativisticTreatment::Zora)
88            .build()
89            .unwrap();
90        println!("{p}");
91        let p = PseudopotentialsBuilder::default()
92            .pspot_beta_phi_type(PSPotBetaPhiType::Real)
93            .pspot_nonlocal_type(PSPotNonlocalType::Reciprocal)
94            .relativistic_treatment(RelativisticTreatment::Zora)
95            .build();
96        assert!(p.is_err());
97        let p = PseudopotentialsBuilder::default()
98            .pspot_nonlocal_type(PSPotNonlocalType::Reciprocal)
99            .relativistic_treatment(RelativisticTreatment::Zora)
100            .build();
101        assert!(p.is_ok());
102        let p = PseudopotentialsBuilder::default()
103            .pspot_beta_phi_type(PSPotBetaPhiType::Reciprocal)
104            .pspot_nonlocal_type(PSPotNonlocalType::Real)
105            .relativistic_treatment(RelativisticTreatment::Zora)
106            .build();
107        assert!(p.is_ok());
108    }
109}