use xtalforge::core::limits::check_supercell;
use xtalforge::core::{Limits as CoreLimits, Structure, make_slab};
use crate::format::StructureFormat;
use crate::{Cli, CliError, input, output};
pub(crate) fn supercell(
cli: &Cli,
path: &str,
repeats: [u32; 3],
out: Option<&str>,
format: Option<StructureFormat>,
) -> Result<(), CliError> {
let structure = input::read_structure_path(path).map_err(CliError::core)?;
check_size(cli, &structure, repeats)?;
let built = structure
.supercell_with_limits(
repeats[0],
repeats[1],
repeats[2],
&CoreLimits::new(cli.limits.profile()),
)
.map_err(CliError::core)?;
output::emit_structure(cli, &built, out, format)
}
pub(crate) fn slab(
cli: &Cli,
path: &str,
hkl: [i32; 3],
layers: u32,
vacuum: f64,
out: Option<&str>,
format: Option<StructureFormat>,
) -> Result<(), CliError> {
let structure = input::read_structure_path(path).map_err(CliError::core)?;
let slab = make_slab(&structure, hkl, layers, vacuum, 0.0).map_err(CliError::core)?;
output::emit_structure(cli, &slab.structure, out, format)
}
fn check_size(cli: &Cli, structure: &Structure, repeats: [u32; 3]) -> Result<(), CliError> {
let [na, nb, nc] = repeats;
let matrix = [
[f64::from(na), 0.0, 0.0],
[0.0, f64::from(nb), 0.0],
[0.0, 0.0, f64::from(nc)],
];
let verdict = check_supercell(
&CoreLimits::new(cli.limits.profile()),
structure.sites().len() as u64,
matrix,
)
.map_err(CliError::core)?;
if verdict.refused() {
return Err(CliError::new("limit_exceeded", verdict.to_string()));
}
if verdict.warned() && !cli.quiet {
eprintln!("warning: {verdict}");
}
Ok(())
}