#![allow(clippy::manual_div_ceil)]
#[allow(unused_imports)]
use super::functions::*;
#[allow(unused_imports)]
use super::functions_2::*;
#[allow(dead_code)]
pub struct ExodusMesh {
pub coordinates: Vec<[f64; 3]>,
pub blocks: Vec<ExodusBlock>,
pub node_sets: Vec<ExodusNodeSet>,
pub side_sets: Vec<ExodusSideSet>,
pub title: String,
}
impl ExodusMesh {
pub fn new(title: &str) -> Self {
ExodusMesh {
coordinates: Vec::new(),
blocks: Vec::new(),
node_sets: Vec::new(),
side_sets: Vec::new(),
title: title.to_string(),
}
}
pub fn add_node(&mut self, x: f64, y: f64, z: f64) -> usize {
self.coordinates.push([x, y, z]);
self.coordinates.len()
}
pub fn add_block(
&mut self,
id: u32,
name: &str,
etype: &str,
n_nodes_per_elem: usize,
) -> usize {
self.blocks.push(ExodusBlock {
id,
name: name.to_string(),
element_type: etype.to_string(),
n_nodes_per_elem,
connectivity: Vec::new(),
});
self.blocks.len() - 1
}
pub fn add_element_to_block(&mut self, block_idx: usize, node_ids: &[usize]) {
self.blocks[block_idx]
.connectivity
.extend_from_slice(node_ids);
}
pub fn add_node_set(&mut self, id: u32, name: &str, nodes: Vec<usize>) {
self.node_sets.push(ExodusNodeSet {
id,
name: name.to_string(),
node_ids: nodes,
});
}
pub fn node_count(&self) -> usize {
self.coordinates.len()
}
pub fn element_count(&self) -> usize {
self.blocks
.iter()
.map(|b| {
b.connectivity
.len()
.checked_div(b.n_nodes_per_elem)
.unwrap_or(0)
})
.sum()
}
}
#[allow(dead_code)]
pub struct ExodusResult {
pub mesh: ExodusMesh,
pub time_steps: Vec<ExodusTimeStep>,
}
impl ExodusResult {
pub fn write_summary(&self) -> String {
let mut s = String::new();
s.push_str(&format!("Title: {}\n", self.mesh.title));
s.push_str(&format!("Nodes: {}\n", self.mesh.node_count()));
s.push_str(&format!("Elements: {}\n", self.mesh.element_count()));
s.push_str(&format!("Blocks: {}\n", self.mesh.blocks.len()));
s.push_str(&format!("Node Sets: {}\n", self.mesh.node_sets.len()));
s.push_str(&format!("Side Sets: {}\n", self.mesh.side_sets.len()));
s.push_str(&format!("Time Steps: {}\n", self.time_steps.len()));
for (i, ts) in self.time_steps.iter().enumerate() {
s.push_str(&format!(
" Step {}: t={:.6}, vars={}\n",
i,
ts.time,
ts.variables.len()
));
}
s
}
}
#[allow(dead_code)]
pub struct ExodusBlock {
pub id: u32,
pub name: String,
pub element_type: String,
pub n_nodes_per_elem: usize,
pub connectivity: Vec<usize>,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ElementQuality {
pub block_id: u32,
pub element_index: usize,
pub aspect_ratio: f64,
pub scaled_jacobian: f64,
pub min_edge: f64,
pub max_edge: f64,
}
#[allow(dead_code)]
pub struct MeshPartition {
pub partition_id: usize,
pub mesh: ExodusMesh,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Default)]
pub struct MeshValidationReport {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
}
impl MeshValidationReport {
pub(super) fn add_error(&mut self, msg: String) {
self.errors.push(msg);
self.is_valid = false;
}
pub(super) fn add_warning(&mut self, msg: String) {
self.warnings.push(msg);
}
}
#[allow(dead_code)]
pub struct ExodusNodeSet {
pub id: u32,
pub name: String,
pub node_ids: Vec<usize>,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FieldStats {
pub min: f64,
pub max: f64,
pub mean: f64,
pub std_dev: f64,
pub count: usize,
}
#[allow(dead_code)]
pub struct ExodusTimeStep {
pub time: f64,
pub variables: Vec<ExodusVariable>,
}
#[allow(dead_code)]
pub struct ExodusSideSet {
pub id: u32,
pub name: String,
pub element_ids: Vec<usize>,
pub side_ids: Vec<usize>,
}
#[allow(dead_code)]
pub struct ExodusGlobalVariable {
pub name: String,
pub time: f64,
pub value: f64,
}
#[allow(dead_code)]
pub struct ExodusVariable {
pub name: String,
pub entity_type: String,
pub values: Vec<f64>,
}
#[allow(dead_code)]
pub struct ExodusSideSetData {
pub id: u32,
pub name: String,
pub element_ids: Vec<usize>,
pub side_ids: Vec<usize>,
pub dist_factors: Vec<f64>,
}
#[allow(dead_code)]
pub struct ExodusWriter;
#[allow(dead_code)]
impl ExodusWriter {
pub fn write_nodal_variable_step(
var_name: &str,
step: usize,
time: f64,
values: &[f64],
) -> String {
let mut s = String::new();
s.push_str(&format!(
"NODAL_VAR {} STEP {} TIME {:.8e}\n",
var_name, step, time
));
let vals: Vec<String> = values.iter().map(|v| format!("{:.8e}", v)).collect();
s.push_str(&vals.join(" "));
s.push('\n');
s.push_str("END_NODAL_VAR\n");
s
}
pub fn write_global_variable(var: &ExodusGlobalVariable) -> String {
format!(
"GLOBAL_VAR {} TIME {:.8e} VALUE {:.8e}\n",
var.name, var.time, var.value
)
}
pub fn write_side_set(data: &ExodusSideSetData) -> String {
let mut s = String::new();
let count = data.element_ids.len();
s.push_str(&format!(
"SIDE_SET_DATA {} {} {}\n",
data.id, data.name, count
));
for i in 0..count {
s.push_str(&format!("{} {}\n", data.element_ids[i], data.side_ids[i]));
}
if !data.dist_factors.is_empty() {
s.push_str("DIST_FACTORS\n");
let fs: Vec<String> = data
.dist_factors
.iter()
.map(|f| format!("{:.6e}", f))
.collect();
s.push_str(&fs.join(" "));
s.push('\n');
}
s.push_str("END_SIDE_SET_DATA\n");
s
}
}