use ndarray::{Array1, Array2};
use num_complex::Complex64;
use refeff_core::{
GenfmtFeffBinHeader, GenfmtFeffBinPotential, GenfmtJasDriverOutput, GenfmtJasPathOutputs,
GenfmtOrdinaryDriverOutput, GenfmtOrdinaryPathOutputs, GenfmtRetainedPathOutput,
};
pub const FEFF_BIN_BOHR: f64 = 0.529_177_249;
pub const FEFF_BIN_DEFAULT_PAD_WIDTH: usize = 8;
#[derive(Debug, Clone, PartialEq)]
pub struct FeffBinPotential {
pub label: String,
pub atomic_number: usize,
}
impl From<GenfmtFeffBinPotential> for FeffBinPotential {
fn from(potential: GenfmtFeffBinPotential) -> Self {
Self {
label: potential.label,
atomic_number: potential.atomic_number,
}
}
}
impl From<&GenfmtFeffBinPotential> for FeffBinPotential {
fn from(potential: &GenfmtFeffBinPotential) -> Self {
potential.clone().into()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FeffBinPath {
pub index: usize,
pub degeneracy: f64,
pub effective_half_path_length_bohr: f64,
pub criterion: f64,
pub potential_indices: Array1<usize>,
pub positions: Array2<f64>,
pub beta: Array1<f64>,
pub eta: Array1<f64>,
pub leg_distances: Array1<f64>,
pub amplitude: Array1<f64>,
pub phase: Array1<f64>,
}
impl FeffBinPath {
#[must_use]
pub fn leg_count(&self) -> usize {
self.potential_indices.len()
}
}
impl From<GenfmtRetainedPathOutput> for FeffBinPath {
fn from(output: GenfmtRetainedPathOutput) -> Self {
Self {
index: output.path_index,
degeneracy: output.degeneracy,
effective_half_path_length_bohr: output.effective_half_path_length_bohr,
criterion: output.criterion_percent,
potential_indices: output.potential_indices,
positions: output.positions,
beta: output.beta_angles,
eta: output.eta_angles,
leg_distances: output.leg_lengths,
amplitude: output.amplitudes,
phase: output.phases,
}
}
}
impl From<&GenfmtRetainedPathOutput> for FeffBinPath {
fn from(output: &GenfmtRetainedPathOutput) -> Self {
output.clone().into()
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FeffBinData {
pub version: String,
pub pad_width: usize,
pub ihole: i32,
pub order: i32,
pub initial_angular_momentum: i32,
pub average_norman_radius: f64,
pub fermi_level: f64,
pub edge_energy: f64,
pub potentials: Vec<FeffBinPotential>,
pub central_phase_shift: Array1<Complex64>,
pub complex_momentum: Array1<Complex64>,
pub real_momentum: Array1<f64>,
pub paths: Vec<FeffBinPath>,
pub raw_text: Option<String>,
}
impl FeffBinData {
#[must_use]
pub fn energy_count(&self) -> usize {
self.central_phase_shift.len()
}
#[must_use]
pub fn potential_count(&self) -> usize {
self.potentials.len()
}
#[must_use]
pub fn from_genfmt_output(
header: &GenfmtFeffBinHeader,
retained_paths: &[GenfmtRetainedPathOutput],
) -> Self {
let mut data = Self::from(header);
data.paths = retained_paths.iter().map(FeffBinPath::from).collect();
data
}
#[must_use]
pub fn from_genfmt_ordinary_outputs(
header: &GenfmtFeffBinHeader,
outputs: &GenfmtOrdinaryPathOutputs,
) -> Self {
Self::from_genfmt_output(header, &outputs.retained_paths)
}
#[must_use]
pub fn from_genfmt_ordinary_driver_output(output: &GenfmtOrdinaryDriverOutput) -> Self {
Self::from_genfmt_ordinary_outputs(&output.header, &output.path_sequence.outputs)
}
#[must_use]
pub fn from_genfmt_jas_outputs(
header: &GenfmtFeffBinHeader,
outputs: &GenfmtJasPathOutputs,
) -> Self {
Self::from_genfmt_output(header, &outputs.retained_paths)
}
#[must_use]
pub fn from_genfmt_jas_driver_output(output: &GenfmtJasDriverOutput) -> Self {
Self::from_genfmt_jas_outputs(&output.header, &output.path_sequence.outputs)
}
}
impl From<GenfmtFeffBinHeader> for FeffBinData {
fn from(header: GenfmtFeffBinHeader) -> Self {
Self {
version: header.version,
pad_width: header.pad_width,
ihole: header.core_hole,
order: header.order,
initial_angular_momentum: header.initial_angular_momentum,
average_norman_radius: header.average_norman_radius,
fermi_level: header.fermi_level,
edge_energy: header.edge_energy,
potentials: header.potentials.into_iter().map(Into::into).collect(),
central_phase_shift: header.central_phase_shifts,
complex_momentum: header.complex_momenta,
real_momentum: header.wave_numbers,
paths: Vec::new(),
raw_text: None,
}
}
}
impl From<&GenfmtFeffBinHeader> for FeffBinData {
fn from(header: &GenfmtFeffBinHeader) -> Self {
header.clone().into()
}
}