conspire 0.7.1

The Rust interface to conspire.
Documentation
pub mod element;
pub mod solid;

use crate::{
    fem::Elements,
    geometry::mesh::PolytopalConnectivity,
    vem::{
        NodalCoordinates, NodalReferenceCoordinates,
        block::element::{ElementNodalCoordinates, VirtualElement},
    },
};
use std::{
    any::type_name,
    fmt::{self, Debug, Formatter},
};

pub struct Block<C, F> {
    constitutive_model: C,
    connectivity: PolytopalConnectivity<3>,
    elements: Vec<F>,
    elements_nodes: Vec<Vec<usize>>,
}

impl<C, F> Block<C, F> {
    fn constitutive_model(&self) -> &C {
        &self.constitutive_model
    }
    fn elements(&self) -> &[F] {
        &self.elements
    }
    fn element_coordinates<'a>(
        coordinates: &'a NodalCoordinates,
        nodes: &[usize],
    ) -> ElementNodalCoordinates<'a> {
        nodes.iter().map(|&node| &coordinates[node]).collect()
    }
    pub fn elements_faces(&self) -> &[Vec<usize>] {
        self.connectivity.elements_faces()
    }
    fn elements_nodes(&self) -> &[Vec<usize>] {
        &self.elements_nodes
    }
    pub fn faces_nodes(&self) -> &[Vec<usize>] {
        self.connectivity.faces_nodes()
    }
}

impl<C, F> Debug for Block<C, F> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Block {{ constitutive model: {}, elements: [Virtual; {}] }}",
            type_name::<C>()
                .rsplit("::")
                .next()
                .unwrap()
                .split("<")
                .next()
                .unwrap(),
            self.elements().len()
        )
    }
}

impl<C, F> Elements for Block<C, F> {
    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]) {
        self.elements_nodes().iter().for_each(|nodes| {
            nodes.iter().for_each(|&node_a| {
                nodes
                    .iter()
                    .for_each(|&node_b| neighbors[node_a].push(node_b))
            })
        })
    }
}

pub trait VirtualElements<C, F>
where
    F: VirtualElement,
    Self: for<'a> From<(C, PolytopalConnectivity<3>, &'a NodalReferenceCoordinates)>,
{
}

impl<C, F> From<(C, PolytopalConnectivity<3>, &NodalReferenceCoordinates)> for Block<C, F>
where
    F: VirtualElement,
{
    fn from(
        (constitutive_model, connectivity, coordinates): (
            C,
            PolytopalConnectivity<3>,
            &NodalReferenceCoordinates,
        ),
    ) -> Self {
        let faces_nodes = connectivity.faces_nodes();
        let (elements, elements_nodes) = connectivity
            .iter()
            .map(|element_faces| {
                let element_coordinates = element_faces
                    .iter()
                    .map(|&face| {
                        faces_nodes[face]
                            .iter()
                            .map(|&node| coordinates[node].clone())
                            .collect()
                    })
                    .collect();
                let mut element_nodes = element_faces
                    .iter()
                    .flat_map(|&face| faces_nodes[face].clone())
                    .collect::<Vec<_>>();
                element_nodes.sort();
                element_nodes.dedup();
                (
                    <F>::from((
                        element_coordinates,
                        element_faces,
                        &element_nodes,
                        faces_nodes,
                    )),
                    element_nodes,
                )
            })
            .unzip();
        Self {
            constitutive_model,
            connectivity,
            elements,
            elements_nodes,
        }
    }
}

impl<C, F>
    From<(
        C,
        Vec<Vec<usize>>,
        Vec<Vec<usize>>,
        &NodalReferenceCoordinates,
    )> for Block<C, F>
where
    F: VirtualElement,
{
    fn from(
        (constitutive_model, elements_faces, faces_nodes, coordinates): (
            C,
            Vec<Vec<usize>>,
            Vec<Vec<usize>>,
            &NodalReferenceCoordinates,
        ),
    ) -> Self {
        Self::from((
            constitutive_model,
            PolytopalConnectivity::from((elements_faces, faces_nodes)),
            coordinates,
        ))
    }
}