conspire 0.7.1

The Rust interface to conspire.
Documentation
use crate::geometry::{Coordinate, Coordinates, grid::Grid, mesh::Connectivity, ntree::Orthotree};
use std::{array::from_fn, collections::HashMap};

impl<const D: usize, const L: usize, const M: usize, const N: usize, U>
    From<Orthotree<D, L, M, N, u16, U>> for (Vec<[usize; N]>, Coordinates<D>)
{
    fn from(orthotree: Orthotree<D, L, M, N, u16, U>) -> Self {
        let mut coord_map: HashMap<u64, usize> = HashMap::new();
        let mut coords: Vec<Coordinate<D>> = Vec::new();
        let face_mask: usize = if D <= 2 { (1 << D) - 1 } else { 3 };
        let connectivity: Vec<[usize; N]> = orthotree
            .nodes
            .iter()
            .filter(|node| node.is_leaf())
            .map(|node| {
                from_fn(|i| {
                    let face = i & face_mask;
                    let vertex_i = (i & !face_mask) | (face ^ (face >> 1));
                    let vertex: [u16; D] = from_fn(|ax| {
                        if (vertex_i >> ax) & 1 == 1 {
                            node.corner[ax] + node.length
                        } else {
                            node.corner[ax]
                        }
                    });
                    let key: u64 =
                        (0..D).fold(0u64, |acc, ax| acc | ((vertex[ax] as u64) << (16 * ax)));
                    if let Some(&idx) = coord_map.get(&key) {
                        idx
                    } else {
                        let idx = coords.len();
                        coords.push(from_fn(|ax| vertex[ax] as f64).into());
                        coord_map.insert(key, idx);
                        idx
                    }
                })
            })
            .collect();
        (connectivity, coords.into())
    }
}

impl<const L: usize, const M: usize, U> From<Orthotree<2, L, M, 4, u16, U>>
    for (Connectivity, Coordinates<2>)
{
    fn from(orthotree: Orthotree<2, L, M, 4, u16, U>) -> Self {
        let (connectivity, coordinates): (Vec<[usize; 4]>, _) = orthotree.into();
        (
            Connectivity::Quadrilateral(connectivity.into()),
            coordinates,
        )
    }
}

impl<const L: usize, const M: usize, U> From<Orthotree<3, L, M, 8, u16, U>>
    for (Connectivity, Coordinates<3>)
{
    fn from(orthotree: Orthotree<3, L, M, 8, u16, U>) -> Self {
        let (connectivity, coordinates): (Vec<[usize; 8]>, _) = orthotree.into();
        (Connectivity::Hexahedral(connectivity.into()), coordinates)
    }
}

impl<const D: usize, const L: usize, const M: usize, const N: usize, T, U, V>
    From<&Orthotree<D, L, M, N, T, U, V>> for Grid<D, V>
where
    T: Copy + Into<usize>,
    V: Copy,
{
    fn from(orthotree: &Orthotree<D, L, M, N, T, U, V>) -> Self {
        let leaves: Vec<([usize; D], usize, V)> = orthotree
            .nodes
            .iter()
            .filter_map(|node| {
                node.value.map(|value| {
                    (
                        from_fn(|ax| node.corner[ax].into()),
                        node.length.into(),
                        value,
                    )
                })
            })
            .collect();
        let nel: [usize; D] = from_fn(|ax| {
            leaves
                .iter()
                .map(|(corner, length, _)| corner[ax] + length)
                .max()
                .unwrap_or(0)
        });
        let count: usize = nel.iter().product();
        if count == 0 {
            return Grid::new(Vec::new(), nel);
        }
        let mut data = vec![leaves[0].2; count];
        for (corner, length, value) in leaves {
            let extent: [usize; D] = from_fn(|ax| (corner[ax] + length).min(nel[ax]) - corner[ax]);
            for cell in 0..extent.iter().product() {
                let mut rem = cell;
                let mut flat = 0;
                let mut stride = 1;
                for ax in 0..D {
                    flat += (corner[ax] + rem % extent[ax]) * stride;
                    rem /= extent[ax];
                    stride *= nel[ax];
                }
                data[flat] = value;
            }
        }
        Grid::new(data, nel)
    }
}