use ndarray::{Array1, Array2, Array3, ArrayView1};
use crate::error::{IoError, Result};
pub const POT_BIN_RADIAL_POINTS: usize = 251;
pub const POT_BIN_ORBITALS: usize = 41;
pub const POT_BIN_COEFFICIENTS: usize = 10;
pub const POT_BIN_IORB_SLOTS: usize = 10;
pub const POT_BIN_MISC_SCALARS: usize = 13;
pub const POT_BIN_DEFAULT_PAD_WIDTH: usize = 8;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PotBinScalars {
pub average_norman_radius: f64,
pub fermi_level: f64,
pub interstitial_potential: f64,
pub interstitial_density: f64,
pub edge_position: f64,
pub amplitude_reduction: f64,
pub relaxation_energy: f64,
pub plasmon_frequency: f64,
pub core_valence_energy: f64,
pub density_radius: f64,
pub fermi_momentum: f64,
pub total_charge: f64,
pub total_volume: f64,
}
impl PotBinScalars {
#[must_use]
pub fn as_array(self) -> [f64; POT_BIN_MISC_SCALARS] {
[
self.average_norman_radius,
self.fermi_level,
self.interstitial_potential,
self.interstitial_density,
self.edge_position,
self.amplitude_reduction,
self.relaxation_energy,
self.plasmon_frequency,
self.core_valence_energy,
self.density_radius,
self.fermi_momentum,
self.total_charge,
self.total_volume,
]
}
pub(super) fn from_slice(values: &[f64]) -> Result<Self> {
if values.len() != POT_BIN_MISC_SCALARS {
return Err(IoError::PotBinShape {
field: "dum",
actual: vec![values.len()],
expected: vec![POT_BIN_MISC_SCALARS],
});
}
Ok(Self {
average_norman_radius: values[0],
fermi_level: values[1],
interstitial_potential: values[2],
interstitial_density: values[3],
edge_position: values[4],
amplitude_reduction: values[5],
relaxation_energy: values[6],
plasmon_frequency: values[7],
core_valence_energy: values[8],
density_radius: values[9],
fermi_momentum: values[10],
total_charge: values[11],
total_volume: values[12],
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct PotBinData {
pub titles: Vec<String>,
pub pad_width: usize,
pub nohole: i32,
pub ihole: i32,
pub interstitial_selector: i32,
pub automatic_folp: i32,
pub jump_mode: i32,
pub unfreeze_f: i32,
pub scalars: PotBinScalars,
pub muffin_tin_indices: Array1<usize>,
pub muffin_tin_radii: Array1<f64>,
pub norman_indices: Array1<usize>,
pub atomic_numbers: Array1<usize>,
pub kappa: Array1<i32>,
pub norman_radii: Array1<f64>,
pub overlap_factors: Array1<f64>,
pub max_overlap_factors: Array1<f64>,
pub potential_multiplicities: Array1<f64>,
pub ionization: Array1<f64>,
pub initial_large_component: Array1<f64>,
pub initial_small_component: Array1<f64>,
pub large_components: Array3<f64>,
pub small_components: Array3<f64>,
pub large_coefficients: Array3<f64>,
pub small_coefficients: Array3<f64>,
pub electron_density: Array2<f64>,
pub coulomb_potential: Array2<f64>,
pub total_potential: Array2<f64>,
pub valence_density: Array2<f64>,
pub valence_potential: Array2<f64>,
pub magnetization_density: Array2<f64>,
pub orbital_occupancy: Array2<f64>,
pub orbital_energies: Array1<f64>,
pub occupied_orbital_indices: Array2<i32>,
pub norman_charges: Array1<f64>,
pub valence_occupancy: Array2<f64>,
pub raw_text: Option<String>,
}
impl PotBinData {
#[must_use]
pub fn potential_count(&self) -> usize {
self.muffin_tin_indices.len()
}
#[must_use]
pub fn angular_count(&self) -> usize {
self.valence_occupancy.nrows()
}
}
#[derive(Debug, Clone)]
pub struct FullSpectrumPotentialState<'a> {
pub titles: &'a [String],
pub atomic_numbers: ArrayView1<'a, usize>,
pub potential_multiplicities: ArrayView1<'a, f64>,
pub norman_radii: ArrayView1<'a, f64>,
}
impl FullSpectrumPotentialState<'_> {
#[must_use]
pub fn title_count(&self) -> usize {
self.titles.len()
}
#[must_use]
pub fn potential_count(&self) -> usize {
self.atomic_numbers.len()
}
#[must_use]
pub fn nph(&self) -> usize {
self.potential_count().saturating_sub(1)
}
}