castep_param_io/param/electronic/bands_option/
mod.rs

1use castep_param_derive::ParamDisplay;
2use derive_builder::Builder;
3pub use extra_bands::ExtraBands;
4pub use nbands::Nbands;
5use serde::{Deserialize, Serialize};
6
7use crate::param::KeywordDisplay;
8
9mod extra_bands;
10/// This keyword determines the maximum number of bands at any k-point and spin.
11/// There are three ways in which you can specify the maximum number of bands at any k-point and spin:
12/// Directly, using `NBANDS`.
13/// Indirectly, by specifying the number of extra bands in addition to the number of occupied bands using `NEXTRA_BANDS`.
14/// This is the method used in the CASTEP interface.
15/// Indirectly, by specifying the number of extra bands in addition to the number of occupied bands as a percentage of the latter value using `PERC_EXTRA_BANDS`.
16/// It is not possible to have both the `NBANDS` keyword and either the `NEXTRA_BANDS` or `PERC_EXTRA_BANDS` keywords present in the same input file.
17#[derive(
18    Debug,
19    Clone,
20    Copy,
21    PartialEq,
22    PartialOrd,
23    Serialize,
24    Deserialize,
25    Builder,
26    Default,
27    ParamDisplay,
28)]
29#[builder(setter(into, strip_option), default)]
30pub struct BandsOption {
31    nbands: Option<Nbands>,
32    extra_bands: Option<ExtraBands>,
33}
34
35mod nbands {
36
37    use castep_param_derive::KeywordDisplay;
38    use serde::{Deserialize, Serialize};
39
40    use crate::param::{ElectronicParam, SpinPolarised};
41
42    use super::extra_bands::ExtraBands;
43
44    #[derive(
45        Debug,
46        Clone,
47        Copy,
48        PartialEq,
49        Eq,
50        PartialOrd,
51        Ord,
52        Hash,
53        Serialize,
54        Deserialize,
55        KeywordDisplay,
56    )]
57    #[keyword_display(field = "NBANDS", from = u32, value=u32)]
58    pub struct Nbands(u32);
59
60    impl Nbands {
61        /// If NEXTRA_BANDS is specified and SPIN_POLARIZED : FALSE:
62        /// NBANDS : (NELECTRONS/2) + NEXTRA_BANDS
63        /// Or, if SPIN_POLARIZED : TRUE:
64        ///     NBANDS : max(NUP, NDOWN) + NEXTRA_BANDS.
65        /// If PERC_EXTRA_BANDS is specified and SPIN_POLARIZED : FALSE:
66        ///     NBANDS : (NELECTRONS/2) × [ 1 + (PERC_EXTRA_BANDS/100)]
67        /// Or, if SPIN_POLARIZED : TRUE:
68        ///     NBANDS : max(NUP, NDOWN) × [ 1 + (PERC_EXTRA_BANDS/100)]
69        /// If NBANDS, NEXTRA_BANDS and PERC_EXTRA_BANDS are not specified and FIX_OCCUPANCY : TRUE, then, if SPIN_POLARIZED : FALSE:
70        ///     NBANDS : NELECTRONS/2.
71        /// Or, if SPIN_POLARIZED : TRUE:
72        ///     NBANDS : max(NUP, NDOWN)
73        /// If FIX_OCCUPANCY : FALSE, these default values of NBANDS will be multiplied by 1.2.
74        pub fn default_value(
75            electronic_param: ElectronicParam,
76            spin_polarised: SpinPolarised,
77            extra_bands: Option<ExtraBands>,
78            // fix_occupancy: FixOccupancy,
79        ) -> Self {
80            if let (Some(ExtraBands::NextraBands(nextra)), SpinPolarised::False) =
81                (extra_bands, spin_polarised)
82            {
83                let nelectrons = electronic_param
84                    .nelectrons
85                    .expect("Number of electrons of the system is not determined!");
86                return Self(nelectrons.value() as u32 / 2 + nextra);
87            }
88            if let (Some(ExtraBands::NextraBands(nextra)), SpinPolarised::True) =
89                (extra_bands, spin_polarised)
90            {
91                let nup = electronic_param
92                    .nup
93                    .expect("NUP of the system is not determined!");
94                let ndown = electronic_param
95                    .ndown
96                    .expect("NDOWN of the system is not determined!");
97                let max = if nup.value() > ndown.value() {
98                    nup.value()
99                } else {
100                    ndown.value()
101                };
102                return Self(max as u32 + nextra);
103            }
104            todo!()
105        }
106    }
107}