Skip to main content

conspire/domain/vem/block/
mod.rs

1pub mod element;
2pub mod solid;
3
4use crate::{
5    fem::Elements,
6    geometry::mesh::PolytopalConnectivity,
7    vem::{
8        NodalCoordinates, NodalReferenceCoordinates,
9        block::element::{ElementNodalCoordinates, VirtualElement},
10    },
11};
12use std::{
13    any::type_name,
14    fmt::{self, Debug, Formatter},
15};
16
17pub struct Block<C, F> {
18    constitutive_model: C,
19    connectivity: PolytopalConnectivity<3>,
20    elements: Vec<F>,
21    elements_nodes: Vec<Vec<usize>>,
22}
23
24impl<C, F> Block<C, F> {
25    fn constitutive_model(&self) -> &C {
26        &self.constitutive_model
27    }
28    fn elements(&self) -> &[F] {
29        &self.elements
30    }
31    fn element_coordinates<'a>(
32        coordinates: &'a NodalCoordinates,
33        nodes: &[usize],
34    ) -> ElementNodalCoordinates<'a> {
35        nodes.iter().map(|&node| &coordinates[node]).collect()
36    }
37    pub fn elements_faces(&self) -> &[Vec<usize>] {
38        self.connectivity.elements_faces()
39    }
40    fn elements_nodes(&self) -> &[Vec<usize>] {
41        &self.elements_nodes
42    }
43    pub fn faces_nodes(&self) -> &[Vec<usize>] {
44        self.connectivity.faces_nodes()
45    }
46}
47
48impl<C, F> Debug for Block<C, F> {
49    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50        write!(
51            f,
52            "Block {{ constitutive model: {}, elements: [Virtual; {}] }}",
53            type_name::<C>()
54                .rsplit("::")
55                .next()
56                .unwrap()
57                .split("<")
58                .next()
59                .unwrap(),
60            self.elements().len()
61        )
62    }
63}
64
65impl<C, F> Elements for Block<C, F> {
66    fn node_neighbors(&self, neighbors: &mut [Vec<usize>]) {
67        self.elements_nodes().iter().for_each(|nodes| {
68            nodes.iter().for_each(|&node_a| {
69                nodes
70                    .iter()
71                    .for_each(|&node_b| neighbors[node_a].push(node_b))
72            })
73        })
74    }
75}
76
77pub trait VirtualElements<C, F>
78where
79    F: VirtualElement,
80    Self: for<'a> From<(C, PolytopalConnectivity<3>, &'a NodalReferenceCoordinates)>,
81{
82}
83
84impl<C, F> From<(C, PolytopalConnectivity<3>, &NodalReferenceCoordinates)> for Block<C, F>
85where
86    F: VirtualElement,
87{
88    fn from(
89        (constitutive_model, connectivity, coordinates): (
90            C,
91            PolytopalConnectivity<3>,
92            &NodalReferenceCoordinates,
93        ),
94    ) -> Self {
95        let faces_nodes = connectivity.faces_nodes();
96        let (elements, elements_nodes) = connectivity
97            .iter()
98            .map(|element_faces| {
99                let element_coordinates = element_faces
100                    .iter()
101                    .map(|&face| {
102                        faces_nodes[face]
103                            .iter()
104                            .map(|&node| coordinates[node].clone())
105                            .collect()
106                    })
107                    .collect();
108                let mut element_nodes = element_faces
109                    .iter()
110                    .flat_map(|&face| faces_nodes[face].clone())
111                    .collect::<Vec<_>>();
112                element_nodes.sort();
113                element_nodes.dedup();
114                (
115                    <F>::from((
116                        element_coordinates,
117                        element_faces,
118                        &element_nodes,
119                        faces_nodes,
120                    )),
121                    element_nodes,
122                )
123            })
124            .unzip();
125        Self {
126            constitutive_model,
127            connectivity,
128            elements,
129            elements_nodes,
130        }
131    }
132}
133
134impl<C, F>
135    From<(
136        C,
137        Vec<Vec<usize>>,
138        Vec<Vec<usize>>,
139        &NodalReferenceCoordinates,
140    )> for Block<C, F>
141where
142    F: VirtualElement,
143{
144    fn from(
145        (constitutive_model, elements_faces, faces_nodes, coordinates): (
146            C,
147            Vec<Vec<usize>>,
148            Vec<Vec<usize>>,
149            &NodalReferenceCoordinates,
150        ),
151    ) -> Self {
152        Self::from((
153            constitutive_model,
154            PolytopalConnectivity::from((elements_faces, faces_nodes)),
155            coordinates,
156        ))
157    }
158}