conspire/domain/vem/block/
mod.rs1pub 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}