#[cfg(feature = "profile")]
use std::time::Instant;
use crate::{
Coordinates, Octree,
fem::hex::{HEX, HexConnectivity, HexahedralFiniteElements},
tree::{Faces, Indices, NodeMap},
};
use conspire::math::{Tensor, TensorVec};
use ndarray::parallel::prelude::*;
use std::collections::HashMap;
pub mod edge_template_1;
mod edge_template_2;
pub mod edge_template_3;
mod edge_template_4;
mod face_template_0;
pub mod face_template_1;
mod vertex_template_1; mod vertex_template_10; mod vertex_template_11; mod vertex_template_12; mod vertex_template_13; mod vertex_template_14; mod vertex_template_15; mod vertex_template_16; mod vertex_template_17; mod vertex_template_18; mod vertex_template_19; mod vertex_template_2; mod vertex_template_20; mod vertex_template_21; mod vertex_template_3; mod vertex_template_4; mod vertex_template_5; mod vertex_template_6; mod vertex_template_7; mod vertex_template_8; mod vertex_template_9;
pub struct HexesAndCoords(HexahedralFiniteElements, Coordinates);
impl From<HexesAndCoords> for (HexahedralFiniteElements, Coordinates) {
fn from(hexes_and_samples: HexesAndCoords) -> Self {
(hexes_and_samples.0, hexes_and_samples.1)
}
}
impl From<&Octree> for HexesAndCoords {
fn from(tree: &Octree) -> Self {
#[cfg(feature = "profile")]
let time = Instant::now();
let mut cells_nodes = vec![0; tree.len()];
let mut coordinates_0 = Coordinates::zero(0);
let mut node_index = 0;
tree.iter()
.enumerate()
.filter(|(_, cell)| cell.is_leaf())
.for_each(|(leaf_index, leaf)| {
cells_nodes[leaf_index] = node_index;
coordinates_0.push(
[
0.5 * (2 * leaf.get_min_x() + leaf.get_lngth()) as f64,
0.5 * (2 * leaf.get_min_y() + leaf.get_lngth()) as f64,
0.5 * (2 * leaf.get_min_z() + leaf.get_lngth()) as f64,
]
.into(),
);
node_index += 1;
});
let mut element_node_connectivity: HexConnectivity = vec![];
let mut nodes_map = HashMap::new();
edge_template_1::apply(
&cells_nodes,
&mut nodes_map,
&mut node_index,
tree,
&mut element_node_connectivity,
&mut coordinates_0,
);
edge_template_3::apply(
&cells_nodes,
&mut nodes_map,
&mut node_index,
tree,
&mut element_node_connectivity,
&mut coordinates_0,
);
face_template_1::apply(
&cells_nodes,
&mut nodes_map,
&mut node_index,
tree,
&mut element_node_connectivity,
&mut coordinates_0,
);
element_node_connectivity.append(
&mut (1..=25)
.into_par_iter()
.flat_map(|index| {
apply_concurrently(index, &cells_nodes, &nodes_map, tree, &coordinates_0)
})
.collect(),
);
let nodal_coordinates = coordinates_0
.iter()
.map(|coordinate| {
[
coordinate[0] * tree.scale.x() + tree.translate.x(),
coordinate[1] * tree.scale.y() + tree.translate.y(),
coordinate[2] * tree.scale.z() + tree.translate.z(),
]
.into()
})
.collect();
let finite_elements = HexahedralFiniteElements::from((
vec![1; element_node_connectivity.len()],
element_node_connectivity,
nodal_coordinates,
));
#[cfg(feature = "profile")]
println!(
" \x1b[1;93mDualization of octree\x1b[0m {:?} ",
time.elapsed()
);
Self(finite_elements, coordinates_0)
}
}
pub fn apply_concurrently(
index: usize,
cells_nodes: &[usize],
nodes_map: &NodeMap,
tree: &Octree,
nodal_coordinates: &Coordinates,
) -> HexConnectivity {
match index {
1 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_1::DATA,
vertex_template_1::template,
),
2 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_2::DATA,
vertex_template_2::template,
),
3 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_3::DATA,
vertex_template_3::template,
),
4 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_4::DATA,
vertex_template_4::template,
),
5 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_5::DATA,
vertex_template_5::template,
),
6 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_6::DATA,
vertex_template_6::template,
),
7 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_7::DATA,
vertex_template_7::template,
),
8 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_8::DATA,
vertex_template_8::template,
),
9 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_9::DATA,
vertex_template_9::template,
),
10 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_10::DATA,
vertex_template_10::template,
),
11 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_11::DATA,
vertex_template_11::template,
),
12 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_12::DATA,
vertex_template_12::template,
),
13 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_13::DATA,
vertex_template_13::template,
),
14 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_14::DATA,
vertex_template_14::template,
),
15 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_15::DATA,
vertex_template_15::template,
),
16 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_16::DATA,
vertex_template_16::template,
),
17 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_17::DATA,
vertex_template_17::template,
),
18 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_18::DATA,
vertex_template_18::template,
),
19 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_19::DATA,
vertex_template_19::template,
),
20 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_20::DATA,
vertex_template_20::template,
),
21 => apply_vertex_template(
cells_nodes,
tree,
vertex_template_21::DATA,
vertex_template_21::template,
),
22 => tree
.iter()
.filter_map(|cell| tree.cell_contains_leaves(cell))
.map(|(cell_subcells, _)| {
[
cells_nodes[cell_subcells[0]],
cells_nodes[cell_subcells[1]],
cells_nodes[cell_subcells[3]],
cells_nodes[cell_subcells[2]],
cells_nodes[cell_subcells[4]],
cells_nodes[cell_subcells[5]],
cells_nodes[cell_subcells[7]],
cells_nodes[cell_subcells[6]],
]
})
.collect(),
23 => face_template_0::apply(cells_nodes, tree),
24 => edge_template_2::apply(cells_nodes, nodes_map, tree, nodal_coordinates),
25 => edge_template_4::apply(cells_nodes, nodes_map, tree, nodal_coordinates),
_ => panic!(),
}
}
fn apply_vertex_template<const T: usize>(
cells_nodes: &[usize],
tree: &Octree,
data: [[usize; 11]; T],
template: impl Fn(
usize,
usize,
usize,
usize,
usize,
usize,
usize,
usize,
usize,
usize,
usize,
&Faces,
&Indices,
&[usize],
&Octree,
) -> Option<[usize; HEX]>,
) -> HexConnectivity {
tree.iter()
.filter_map(|cell| tree.cell_contains_leaves(cell))
.flat_map(|(cell_subcells, cell_faces)| {
data.iter()
.filter_map(|data| {
template(
data[0],
data[1],
data[2],
data[3],
data[4],
data[5],
data[6],
data[7],
data[8],
data[9],
data[10],
cell_faces,
cell_subcells,
cells_nodes,
tree,
)
})
.collect::<HexConnectivity>()
})
.collect()
}