conspire 0.7.0

The Rust interface to conspire.
Documentation
use crate::{
    constitutive::solid::hyperelastic::NeoHookean,
    fem::{Model, solid::elastic::ElasticElements},
    geometry::mesh::{Connectivity, Mesh, PolytopalConnectivity},
    math::{
        Tensor,
        test::{TestError, assert_eq},
    },
    vem::{
        NodalCoordinates, NodalReferenceCoordinates,
        block::{Block, element::Element},
    },
};

fn constitutive_model() -> NeoHookean {
    NeoHookean {
        bulk_modulus: 13.0,
        shear_modulus: 3.0,
    }
}

fn coordinates() -> NodalReferenceCoordinates {
    NodalReferenceCoordinates::from(vec![
        [0.0, 0.0, 0.0],
        [1.0, 0.0, 0.0],
        [0.0, 1.0, 0.0],
        [1.0, 1.0, 0.0],
        [0.0, 0.0, 1.0],
        [1.0, 0.0, 1.0],
        [0.0, 1.0, 1.0],
        [1.0, 1.0, 1.0],
    ])
}

fn deformed_coordinates() -> NodalCoordinates {
    coordinates()
        .iter()
        .map(|coordinate| {
            [
                1.1 * coordinate[0] + 0.05 * coordinate[1],
                0.95 * coordinate[1],
                1.05 * coordinate[2],
            ]
        })
        .collect::<Vec<_>>()
        .into()
}

fn elements_faces() -> Vec<Vec<usize>> {
    vec![vec![0, 1, 2, 3, 4, 5]]
}

fn faces_nodes() -> Vec<Vec<usize>> {
    vec![
        vec![0, 2, 3, 1],
        vec![4, 5, 7, 6],
        vec![0, 1, 5, 4],
        vec![2, 6, 7, 3],
        vec![0, 4, 6, 2],
        vec![1, 3, 7, 5],
    ]
}

#[test]
fn polyhedral_block_nodal_forces() -> Result<(), TestError> {
    let mesh = Mesh::from((
        vec![Connectivity::Polyhedral(PolytopalConnectivity::from((
            elements_faces(),
            faces_nodes(),
        )))],
        coordinates(),
    ));
    let model: Model<Block<NeoHookean, Element>, 3> = (mesh, constitutive_model())
        .try_into()
        .map_err(|error: String| TestError { message: error })?;
    let block = Block::<NeoHookean, Element>::from((
        constitutive_model(),
        elements_faces(),
        faces_nodes(),
        &coordinates(),
    ));
    assert_eq(
        &block.nodal_forces(&deformed_coordinates())?,
        &ElasticElements::nodal_forces(&model, &deformed_coordinates())?,
    )
}

#[test]
fn wrong_element_kind() {
    let mesh = Mesh::from((
        vec![Connectivity::Tetrahedral(
            vec![[0, 1, 2, 4], [1, 3, 2, 7]].into(),
        )],
        coordinates(),
    ));
    let model: Result<Model<Block<NeoHookean, Element>, 3>, String> =
        (mesh, constitutive_model()).try_into();
    assert_eq!(model.err().unwrap(), "block is not polyhedral")
}