conspire 0.7.1

The Rust interface to conspire.
Documentation
#[cfg(test)]
mod test;

use crate::{
    fem::{
        Blocks, ElasticViscoplasticAndElastic, Model, NodalReferenceCoordinates,
        block::{
            Block,
            element::{
                ElementNodalReferenceCoordinates, FiniteElement,
                planar::PlanarElementNodalReferenceCoordinates,
            },
        },
    },
    geometry::mesh::{Connectivities, Connectivity, Mesh, PrimitiveConnectivity},
};

fn block<C, F, const D: usize, const G: usize, const N: usize, const P: usize>(
    constitutive_model: C,
    connectivity: Connectivity,
    coordinates: &NodalReferenceCoordinates<D>,
) -> Result<Block<C, F, G, D, N, P>, String>
where
    Block<C, F, G, D, N, P>: for<'a> From<(
        C,
        PrimitiveConnectivity<D, N>,
        &'a NodalReferenceCoordinates<D>,
    )>,
    PrimitiveConnectivity<D, N>: TryFrom<Connectivity, Error = &'static str>,
{
    Ok(Block::from((
        constitutive_model,
        PrimitiveConnectivity::<D, N>::try_from(connectivity)?,
        coordinates,
    )))
}

impl<C, F, const G: usize, const N: usize, const P: usize> TryFrom<(Mesh<3>, C)>
    for Model<Block<C, F, G, 3, N, P>, 3>
where
    F: FiniteElement<G, 3, N, P> + From<ElementNodalReferenceCoordinates<N>>,
    PrimitiveConnectivity<3, N>: TryFrom<Connectivity, Error = &'static str>,
{
    type Error = String;
    fn try_from((mesh, constitutive_model): (Mesh<3>, C)) -> Result<Self, Self::Error> {
        let (connectivities, coordinates): (Connectivities, NodalReferenceCoordinates<3>) =
            mesh.into();
        let mut connectivities = connectivities.into_members();
        if connectivities.len() != 1 {
            return Err(format!(
                "mesh has {} blocks, model type expects 1",
                connectivities.len()
            ));
        }
        Ok(Self {
            blocks: block(constitutive_model, connectivities.remove(0), &coordinates)?,
            coordinates,
        })
    }
}

impl<C, F, const G: usize, const N: usize, const P: usize> TryFrom<(Mesh<2>, C)>
    for Model<Block<C, F, G, 2, N, P>, 2>
where
    F: FiniteElement<G, 2, N, P> + From<PlanarElementNodalReferenceCoordinates<N>>,
    PrimitiveConnectivity<2, N>: TryFrom<Connectivity, Error = &'static str>,
{
    type Error = String;
    fn try_from((mesh, constitutive_model): (Mesh<2>, C)) -> Result<Self, Self::Error> {
        let (connectivities, coordinates): (Connectivities, NodalReferenceCoordinates<2>) =
            mesh.into();
        let mut connectivities = connectivities.into_members();
        if connectivities.len() != 1 {
            return Err(format!(
                "mesh has {} blocks, model type expects 1",
                connectivities.len()
            ));
        }
        Ok(Self {
            blocks: block(constitutive_model, connectivities.remove(0), &coordinates)?,
            coordinates,
        })
    }
}

impl<
    C1,
    C2,
    F1,
    F2,
    const G1: usize,
    const N1: usize,
    const P1: usize,
    const G2: usize,
    const N2: usize,
    const P2: usize,
> TryFrom<(Mesh<3>, (C1, C2))>
    for Model<Blocks<Block<C1, F1, G1, 3, N1, P1>, Block<C2, F2, G2, 3, N2, P2>>, 3>
where
    F1: FiniteElement<G1, 3, N1, P1> + From<ElementNodalReferenceCoordinates<N1>>,
    F2: FiniteElement<G2, 3, N2, P2> + From<ElementNodalReferenceCoordinates<N2>>,
    PrimitiveConnectivity<3, N1>: TryFrom<Connectivity, Error = &'static str>,
    PrimitiveConnectivity<3, N2>: TryFrom<Connectivity, Error = &'static str>,
{
    type Error = String;
    fn try_from(
        (mesh, (constitutive_model_1, constitutive_model_2)): (Mesh<3>, (C1, C2)),
    ) -> Result<Self, Self::Error> {
        let (connectivities, coordinates): (Connectivities, NodalReferenceCoordinates<3>) =
            mesh.into();
        let mut connectivities = connectivities.into_members().into_iter();
        if connectivities.len() != 2 {
            return Err(format!(
                "mesh has {} blocks, model type expects 2",
                connectivities.len()
            ));
        }
        Ok(Self {
            blocks: Blocks(
                block(
                    constitutive_model_1,
                    connectivities.next().unwrap(),
                    &coordinates,
                )?,
                block(
                    constitutive_model_2,
                    connectivities.next().unwrap(),
                    &coordinates,
                )?,
            ),
            coordinates,
        })
    }
}

impl<
    C1,
    C2,
    F1,
    F2,
    const G1: usize,
    const N1: usize,
    const P1: usize,
    const G2: usize,
    const N2: usize,
    const P2: usize,
> TryFrom<(Mesh<3>, (C1, C2))>
    for Model<
        ElasticViscoplasticAndElastic<Block<C1, F1, G1, 3, N1, P1>, Block<C2, F2, G2, 3, N2, P2>>,
        3,
    >
where
    F1: FiniteElement<G1, 3, N1, P1> + From<ElementNodalReferenceCoordinates<N1>>,
    F2: FiniteElement<G2, 3, N2, P2> + From<ElementNodalReferenceCoordinates<N2>>,
    PrimitiveConnectivity<3, N1>: TryFrom<Connectivity, Error = &'static str>,
    PrimitiveConnectivity<3, N2>: TryFrom<Connectivity, Error = &'static str>,
{
    type Error = String;
    fn try_from(
        (mesh, (constitutive_model_1, constitutive_model_2)): (Mesh<3>, (C1, C2)),
    ) -> Result<Self, Self::Error> {
        let (connectivities, coordinates): (Connectivities, NodalReferenceCoordinates<3>) =
            mesh.into();
        let mut connectivities = connectivities.into_members().into_iter();
        if connectivities.len() != 2 {
            return Err(format!(
                "mesh has {} blocks, model type expects 2",
                connectivities.len()
            ));
        }
        Ok(Self {
            blocks: ElasticViscoplasticAndElastic(
                block(
                    constitutive_model_1,
                    connectivities.next().unwrap(),
                    &coordinates,
                )?,
                block(
                    constitutive_model_2,
                    connectivities.next().unwrap(),
                    &coordinates,
                )?,
            ),
            coordinates,
        })
    }
}