use super::{ErrorWrapper, io::read_mesh};
use conspire::{
geometry::mesh::{Mesh, Verdict},
io::{Npy, Write},
};
use std::{
fs::File,
io::{BufWriter, Write as WriteIO},
time::Instant,
};
#[derive(clap::Args)]
pub struct MetricsArgs {
#[arg(long, short, value_name = "FILE")]
pub input: String,
#[arg(long, short, value_name = "FILE")]
pub output: String,
}
pub fn metrics(args: MetricsArgs, quiet: bool) -> Result<(), ErrorWrapper> {
let mesh = read_mesh(&args.input, quiet, true)?;
write_metrics(&mesh, &args.output, quiet)
}
fn flatten(metric: Vec<Vec<f64>>) -> Vec<f64> {
metric.into_iter().flatten().collect()
}
pub fn write_metrics(mesh: &Mesh<3>, file: &str, quiet: bool) -> Result<(), ErrorWrapper> {
crate::echo!(quiet, " \x1b[1;96mMetrics\x1b[0m {file}");
let time = Instant::now();
let maximum_edge_ratios = flatten(mesh.maximum_edge_ratios());
let minimum_scaled_jacobians = flatten(mesh.minimum_scaled_jacobians());
let maximum_skews = flatten(mesh.maximum_skews());
let volumes = flatten(mesh.volumes());
let extension = super::io::extension(file);
match extension {
Some("csv") => {
let mut writer = BufWriter::new(File::create(file)?);
writer.write_all(
b"maximum edge ratio,minimum scaled jacobian,maximum skew,element volume\n",
)?;
for (((ratio, jacobian), skew), volume) in maximum_edge_ratios
.iter()
.zip(minimum_scaled_jacobians.iter())
.zip(maximum_skews.iter())
.zip(volumes.iter())
{
writer.write_all(
format!("{ratio:>10.6e},{jacobian:>10.6e},{skew:>10.6e},{volume:>10.6e}\n")
.as_bytes(),
)?;
}
writer.flush()?;
}
Some("npy") => {
let rows = maximum_edge_ratios.len();
let mut data = Vec::with_capacity(rows * 4);
for (((ratio, jacobian), skew), volume) in maximum_edge_ratios
.iter()
.zip(minimum_scaled_jacobians.iter())
.zip(maximum_skews.iter())
.zip(volumes.iter())
{
data.push(*ratio);
data.push(*jacobian);
data.push(*skew);
data.push(*volume);
}
Npy {
data,
shape: vec![rows, 4],
fortran_order: false,
}
.write(file)?;
}
_ => {
return Err(ErrorWrapper::from(format!(
"Unsupported metrics extension .{} (use csv or npy)",
extension.unwrap_or("UNDEFINED")
)));
}
}
crate::echo!(quiet, " \x1b[1;92mDone\x1b[0m {:?}", time.elapsed());
Ok(())
}