use super::{Error, Mesh, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FieldLocation {
Point,
Cell,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Field {
pub name: String,
pub location: FieldLocation,
pub components: Vec<String>,
pub values: Vec<f64>,
pub step: Option<i64>,
pub time: Option<f64>,
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Dataset {
pub mesh: Mesh,
pub fields: Vec<Field>,
}
impl Dataset {
pub fn validate(&self) -> Result<()> {
self.mesh.validate()?;
for field in &self.fields {
if field.name.is_empty() || field.components.is_empty() {
return Err(Error::new(
"E_FIELD",
"field name and components must be nonempty",
));
}
let entities = match field.location {
FieldLocation::Point => self.mesh.points.len(),
FieldLocation::Cell => self.mesh.cells.len(),
};
if field.values.len() != entities.saturating_mul(field.components.len()) {
return Err(Error::new(
"E_FIELD",
format!("field {} has an invalid value count", field.name),
));
}
if !field.values.iter().all(|value| value.is_finite())
|| field.time.is_some_and(|time| !time.is_finite())
{
return Err(Error::new(
"E_NONFINITE",
format!("field {} contains a nonfinite value", field.name),
));
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{Dataset, Field, FieldLocation, Mesh};
use crate::core::Point;
#[test]
fn field_validation_rejects_incomplete_or_nonfinite_data() {
let mut dataset = Dataset {
mesh: Mesh {
points: vec![Point {
id: 1,
position: [0.0; 3],
}],
..Mesh::default()
},
fields: vec![Field {
name: "DISP".into(),
location: FieldLocation::Point,
components: vec!["T1".into()],
values: vec![0.0],
step: None,
time: None,
}],
};
assert!(dataset.validate().is_ok());
dataset.fields[0].name.clear();
assert_eq!(dataset.validate().unwrap_err().code, "E_FIELD");
dataset.fields[0].name = "DISP".into();
dataset.fields[0].components.clear();
assert_eq!(dataset.validate().unwrap_err().code, "E_FIELD");
dataset.fields[0].components.push("T1".into());
dataset.fields[0].values.clear();
assert_eq!(dataset.validate().unwrap_err().code, "E_FIELD");
dataset.fields[0].values.push(f64::INFINITY);
assert_eq!(dataset.validate().unwrap_err().code, "E_NONFINITE");
dataset.fields[0].values[0] = 0.0;
dataset.fields[0].time = Some(f64::NAN);
assert_eq!(dataset.validate().unwrap_err().code, "E_NONFINITE");
}
}