1#[cfg(feature = "serde")]
4use crate::traits::ConvertToSerializable;
5use crate::traits::Topology;
6use itertools::izip;
7use ndelement::{orientation::compute_orientation, reference_cell, types::ReferenceCellType};
8use rlst::DynArray;
9use std::collections::HashMap;
10use std::iter::Copied;
11
12#[derive(Debug)]
14pub struct MixedTopology {
15 dim: usize,
16 pub(crate) ids: HashMap<ReferenceCellType, Vec<usize>>,
17 pub(crate) ids_to_indices: HashMap<ReferenceCellType, HashMap<usize, usize>>,
18 pub(crate) insertion_indices: HashMap<ReferenceCellType, Vec<usize>>,
19 entity_types: Vec<Vec<ReferenceCellType>>,
20 entity_counts: HashMap<ReferenceCellType, usize>,
21 pub(crate) downward_connectivity:
22 HashMap<ReferenceCellType, HashMap<ReferenceCellType, DynArray<usize, 2>>>,
23 pub(crate) upward_connectivity:
24 HashMap<ReferenceCellType, HashMap<ReferenceCellType, Vec<Vec<usize>>>>,
25 pub(crate) orientation: HashMap<ReferenceCellType, Vec<i32>>,
26}
27
28#[cfg(feature = "serde")]
29#[derive(serde::Serialize, Debug, serde::Deserialize)]
30pub struct SerializableTopology {
32 dim: usize,
33 ids: HashMap<ReferenceCellType, Vec<usize>>,
34 ids_to_indices: HashMap<ReferenceCellType, HashMap<usize, usize>>,
35 insertion_indices: HashMap<ReferenceCellType, Vec<usize>>,
36 entity_types: Vec<Vec<ReferenceCellType>>,
37 entity_counts: HashMap<ReferenceCellType, usize>,
38 #[allow(clippy::type_complexity)]
39 downward_connectivity:
40 HashMap<ReferenceCellType, HashMap<ReferenceCellType, (Vec<usize>, [usize; 2])>>,
41 upward_connectivity: HashMap<ReferenceCellType, HashMap<ReferenceCellType, Vec<Vec<usize>>>>,
42 orientation: HashMap<ReferenceCellType, Vec<i32>>,
43}
44
45#[cfg(feature = "serde")]
46impl ConvertToSerializable for MixedTopology {
47 type SerializableType = SerializableTopology;
48 fn to_serializable(&self) -> SerializableTopology {
49 SerializableTopology {
50 dim: self.dim,
51 ids: self.ids.clone(),
52 ids_to_indices: self.ids_to_indices.clone(),
53 insertion_indices: self.insertion_indices.clone(),
54 entity_types: self.entity_types.clone(),
55 entity_counts: self.entity_counts.clone(),
56 downward_connectivity: self
57 .downward_connectivity
58 .iter()
59 .map(|(a, b)| {
60 (
61 *a,
62 b.iter()
63 .map(|(c, d)| (*c, (d.data().unwrap().to_vec(), d.shape())))
64 .collect::<HashMap<_, _>>(),
65 )
66 })
67 .collect::<HashMap<_, _>>(),
68 upward_connectivity: self.upward_connectivity.clone(),
69 orientation: self.orientation.clone(),
70 }
71 }
72 fn from_serializable(s: SerializableTopology) -> Self {
73 Self {
74 dim: s.dim,
75 ids: s.ids,
76 ids_to_indices: s.ids_to_indices,
77 insertion_indices: s.insertion_indices,
78 entity_types: s.entity_types,
79 entity_counts: s.entity_counts,
80 downward_connectivity: s
81 .downward_connectivity
82 .iter()
83 .map(|(a, b)| {
84 (
85 *a,
86 b.iter()
87 .map(|(c, (data, shape))| {
88 (*c, {
89 let mut d = DynArray::<usize, 2>::from_shape(*shape);
90 d.data_mut().unwrap().copy_from_slice(data);
91 d
92 })
93 })
94 .collect::<HashMap<_, _>>(),
95 )
96 })
97 .collect::<HashMap<_, _>>(),
98 upward_connectivity: s.upward_connectivity,
99 orientation: s.orientation,
100 }
101 }
102}
103
104impl MixedTopology {
105 pub fn new(
107 cells: &[usize],
108 cell_types: &[ReferenceCellType],
109 vertex_ids: Option<Vec<usize>>,
110 cell_ids: Option<Vec<usize>>,
111 ) -> Self {
112 let mut start = 0;
113
114 let dim = reference_cell::dim(cell_types[0]);
115 for ct in cell_types {
117 if reference_cell::dim(*ct) != dim {
118 panic!(
119 "MixedTopology does not support cells of a mixture of topological dimensions"
120 );
121 }
122 }
123
124 let mut entities = HashMap::new();
125 let mut entity_counts = HashMap::new();
126 entity_counts.insert(ReferenceCellType::Point, cells.iter().max().unwrap() + 1);
127
128 let mut ids = HashMap::new();
129 let mut ids_to_indices = HashMap::new();
130 if let Some(i) = vertex_ids {
131 ids_to_indices.insert(ReferenceCellType::Point, {
132 let mut vids = HashMap::new();
133 for (j, k) in i.iter().enumerate() {
134 vids.insert(*k, j);
135 }
136 vids
137 });
138 ids.insert(ReferenceCellType::Point, i);
139 }
140
141 let mut insertion_indices = HashMap::new();
142 for (cell_index, cell_type) in cell_types.iter().enumerate() {
143 let size = reference_cell::entity_counts(*cell_type)[0];
144 insertion_indices
145 .entry(*cell_type)
146 .or_insert(vec![])
147 .push(cell_index);
148
149 let cell = &cells[start..start + size];
151 if let Some(i) = &cell_ids {
152 ids.entry(*cell_type).or_insert(vec![]).push(i[cell_index]);
153 ids_to_indices
154 .entry(*cell_type)
155 .or_insert(HashMap::new())
156 .insert(
157 i[cell_index],
158 if let Some(j) = entity_counts.get(cell_type) {
159 *j
160 } else {
161 0
162 },
163 );
164 }
165
166 for (etypes, rc_i) in izip!(
168 &reference_cell::entity_types(*cell_type),
169 &reference_cell::connectivity(*cell_type)
170 ) {
171 for (etype, c_ij) in izip!(etypes, rc_i) {
172 let mut entity = c_ij[0].iter().map(|i| cell[*i]).collect::<Vec<_>>();
173 entity.sort();
174 entities
175 .entry(*etype)
176 .or_insert(HashMap::new())
177 .entry(entity)
178 .or_insert_with(|| {
179 let old = *entity_counts.entry(*etype).or_insert(0);
180 *entity_counts.get_mut(etype).unwrap() += 1;
181 old
182 });
183 }
184 }
185 start += size;
186 }
187
188 let mut entity_types = vec![vec![]; dim + 1];
189 for e in entity_counts.keys() {
190 entity_types[reference_cell::dim(*e)].push(*e);
191 }
192
193 let mut downward_connectivity = HashMap::new();
197 for (etype, ecount) in &entity_counts {
199 downward_connectivity.insert(*etype, {
200 let mut dc = HashMap::new();
201 for sub_etypes in &reference_cell::entity_types(*etype) {
202 for e in sub_etypes {
203 dc.entry(*e).or_insert(DynArray::<usize, 2>::from_shape([
204 sub_etypes.iter().filter(|&i| *i == *e).count(),
205 *ecount,
206 ]));
207 }
208 }
209 dc
210 });
211 }
212
213 let mut upward_connectivity = HashMap::new();
217 for etype in entity_counts.keys() {
219 for sub_etypes in reference_cell::entity_types(*etype)
220 .iter()
221 .take(reference_cell::dim(*etype))
222 {
223 for e in sub_etypes {
224 upward_connectivity
225 .entry(*e)
226 .or_insert(HashMap::new())
227 .entry(*etype)
228 .or_insert(vec![vec![]; entity_counts[e]]);
229 }
230 }
231 }
232
233 for (d, dc) in downward_connectivity.iter_mut() {
235 for (i, mut j) in dc.get_mut(d).unwrap().col_iter_mut().enumerate() {
236 j[[0]] = i;
237 }
238 }
239
240 for (etype, entities_vertices) in &entities {
242 for (vs, entity_index) in entities_vertices {
243 for (i, vertex_index) in vs.iter().enumerate() {
244 downward_connectivity
245 .get_mut(etype)
246 .unwrap()
247 .get_mut(&ReferenceCellType::Point)
248 .unwrap()[[i, *entity_index]] = *vertex_index;
249 if reference_cell::dim(*etype) > 0 {
251 let uc = upward_connectivity
252 .get_mut(&ReferenceCellType::Point)
253 .unwrap()
254 .get_mut(etype)
255 .unwrap();
256 if !uc[*vertex_index].contains(entity_index) {
257 uc[*vertex_index].push(*entity_index);
258 }
259 }
260 }
261 }
262 }
263
264 if dim > 0 {
266 for etype in &entity_types[dim] {
267 let entity_types = reference_cell::entity_types(*etype);
268 let ref_conn = reference_cell::connectivity(*etype);
269 let mut cell_entities = ref_conn
271 .iter()
272 .skip(1)
273 .map(|i| vec![0; i.len()])
274 .collect::<Vec<_>>();
275 for (cell, cell_index) in &entities[etype] {
276 cell_entities[dim - 1][0] = *cell_index;
278
279 for (ce_i, rc_i, et_i) in izip!(
281 cell_entities.iter_mut(),
282 ref_conn.iter().skip(1),
283 entity_types.iter().skip(1),
284 ) {
285 for (ce_ij, rc_ij, et_ij) in izip!(ce_i.iter_mut(), rc_i, et_i) {
286 let mut entity = rc_ij[0].iter().map(|i| cell[*i]).collect::<Vec<_>>();
287 entity.sort();
288 *ce_ij = *entities[et_ij].get(&entity).unwrap();
289 }
290 }
291
292 for (i, (rc_i, ce_i, et_i)) in izip!(
293 ref_conn.iter().skip(2),
294 cell_entities.iter().skip(1),
295 entity_types.iter().skip(2),
296 )
297 .enumerate()
298 {
299 for (ce_ij, rc_ij, et_ij) in izip!(ce_i, rc_i, et_i) {
300 for (k, (rc_ijk, ce_k)) in
301 izip!(rc_ij.iter().take(i + 2).skip(1), &cell_entities).enumerate()
302 {
303 let mut sub_entity_indices = HashMap::new();
304 for (sub_entity_type, rc_ijkl) in
305 izip!(&entity_types[k + 1], rc_ijk)
306 {
307 let sub_entity_index = sub_entity_indices
308 .entry(sub_entity_type)
309 .and_modify(|e| *e += 1)
310 .or_insert(0);
311 downward_connectivity
312 .get_mut(et_ij)
313 .unwrap()
314 .get_mut(sub_entity_type)
315 .unwrap()[[*sub_entity_index, *ce_ij]] = ce_k[*rc_ijkl];
316 let uc = upward_connectivity
317 .get_mut(sub_entity_type)
318 .unwrap()
319 .get_mut(et_ij)
320 .unwrap();
321 if !uc[ce_k[*rc_ijkl]].contains(ce_ij) {
322 uc[ce_k[*rc_ijkl]].push(*ce_ij);
323 }
324 }
325 }
326 }
327 }
328 }
329 }
330 }
331
332 let mut orientation = HashMap::new();
333 for types in entity_types.iter().skip(1) {
334 for t in types {
335 let dc = &downward_connectivity[t][&ReferenceCellType::Point];
336 orientation.insert(
337 *t,
338 (0..dc.shape()[1])
339 .map(|i| {
340 compute_orientation(
341 *t,
342 &dc.data().unwrap()[i * dc.shape()[0]..(i + 1) * dc.shape()[0]],
343 )
344 })
345 .collect::<Vec<_>>(),
346 );
347 }
348 }
349
350 Self {
351 dim,
352 ids,
353 ids_to_indices,
354 insertion_indices,
355 entity_types,
356 entity_counts,
357 downward_connectivity,
358 upward_connectivity,
359 orientation,
360 }
361 }
362 pub fn dim(&self) -> usize {
364 self.dim
365 }
366 pub fn entity_types(&self) -> &[Vec<ReferenceCellType>] {
368 &self.entity_types
369 }
370 pub fn entity_counts(&self) -> &HashMap<ReferenceCellType, usize> {
372 &self.entity_counts
373 }
374 pub fn entity_count(&self, entity_type: ReferenceCellType) -> usize {
376 if let Some(n) = self.entity_counts.get(&entity_type) {
377 *n
378 } else {
379 0
380 }
381 }
382 pub fn cell_entity_index(
384 &self,
385 cell_type: ReferenceCellType,
386 cell_index: usize,
387 entity_type: ReferenceCellType,
388 entity_index: usize,
389 ) -> usize {
390 self.downward_connectivity[&cell_type][&entity_type][[entity_index, cell_index]]
391 }
392 pub fn entity_id(&self, entity_type: ReferenceCellType, entity_index: usize) -> Option<usize> {
394 self.ids.get(&entity_type).map(|a| a[entity_index])
395 }
396}
397
398#[derive(Debug)]
400pub struct MixedEntityTopology<'a> {
401 topology: &'a MixedTopology,
402 entity_type: ReferenceCellType,
403 entity_index: usize,
404}
405
406impl<'t> MixedEntityTopology<'t> {
407 pub fn new(
409 topology: &'t MixedTopology,
410 entity_type: ReferenceCellType,
411 entity_index: usize,
412 ) -> Self {
413 Self {
414 topology,
415 entity_type,
416 entity_index,
417 }
418 }
419}
420
421impl Topology for MixedEntityTopology<'_> {
422 type EntityDescriptor = ReferenceCellType;
423 type EntityIndexIter<'a>
424 = Copied<std::slice::Iter<'a, usize>>
425 where
426 Self: 'a;
427
428 type ConnectedEntityIndexIter<'a>
429 = Copied<std::slice::Iter<'a, usize>>
430 where
431 Self: 'a;
432
433 fn connected_entity_iter(
434 &self,
435 entity_type: ReferenceCellType,
436 ) -> Copied<std::slice::Iter<'_, usize>> {
437 self.topology.upward_connectivity[&self.entity_type][&entity_type][self.entity_index]
438 .iter()
439 .copied()
440 }
441
442 fn sub_entity_iter(
443 &self,
444 entity_type: ReferenceCellType,
445 ) -> Copied<std::slice::Iter<'_, usize>> {
446 let rows = self.topology.downward_connectivity[&self.entity_type][&entity_type].shape()[0];
447 self.topology.downward_connectivity[&self.entity_type][&entity_type]
448 .data()
449 .unwrap()[rows * self.entity_index..rows * (self.entity_index + 1)]
450 .iter()
451 .copied()
452 }
453
454 fn sub_entity(&self, entity_type: ReferenceCellType, index: usize) -> usize {
455 self.topology.downward_connectivity[&self.entity_type][&entity_type]
456 [[index, self.entity_index]]
457 }
458
459 fn orientation(&self) -> i32 {
460 if reference_cell::dim(self.entity_type) == 0 {
461 0
462 } else {
463 self.topology.orientation[&self.entity_type][self.entity_index]
464 }
465 }
466}
467
468#[cfg(test)]
469mod test {
470 use super::*;
471
472 fn example_topology_triangle_and_quad() -> MixedTopology {
473 MixedTopology::new(
475 &[0, 1, 2, 3, 1, 3, 4],
476 &[
477 ReferenceCellType::Quadrilateral,
478 ReferenceCellType::Triangle,
479 ],
480 None,
481 None,
482 )
483 }
484
485 #[test]
486 fn test_prism() {
487 let _ = MixedTopology::new(&[0, 1, 2, 3, 4, 5], &[ReferenceCellType::Prism], None, None);
488 }
489 #[test]
490 fn test_pyramid() {
491 let _ = MixedTopology::new(&[0, 1, 2, 3, 4], &[ReferenceCellType::Pyramid], None, None);
492 }
493
494 #[test]
495 fn test_sub_entities_triangle_and_quad() {
496 let t = example_topology_triangle_and_quad();
498 let cell0 = MixedEntityTopology::new(&t, ReferenceCellType::Quadrilateral, 0);
499 assert_eq!(cell0.sub_entity(ReferenceCellType::Point, 0), 0);
500 assert_eq!(cell0.sub_entity(ReferenceCellType::Point, 1), 1);
501 assert_eq!(cell0.sub_entity(ReferenceCellType::Point, 2), 2);
502 assert_eq!(cell0.sub_entity(ReferenceCellType::Point, 3), 3);
503 assert_eq!(cell0.sub_entity(ReferenceCellType::Interval, 0), 0);
504 assert_eq!(cell0.sub_entity(ReferenceCellType::Interval, 1), 1);
505 assert_eq!(cell0.sub_entity(ReferenceCellType::Interval, 2), 2);
506 assert_eq!(cell0.sub_entity(ReferenceCellType::Interval, 3), 3);
507 assert_eq!(cell0.sub_entity(ReferenceCellType::Quadrilateral, 0), 0);
508 let cell1 = MixedEntityTopology::new(&t, ReferenceCellType::Triangle, 0);
509 assert_eq!(cell1.sub_entity(ReferenceCellType::Point, 0), 1);
510 assert_eq!(cell1.sub_entity(ReferenceCellType::Point, 1), 3);
511 assert_eq!(cell1.sub_entity(ReferenceCellType::Point, 2), 4);
512 assert_eq!(cell1.sub_entity(ReferenceCellType::Interval, 0), 4);
513 assert_eq!(cell1.sub_entity(ReferenceCellType::Interval, 1), 5);
514 assert_eq!(cell1.sub_entity(ReferenceCellType::Interval, 2), 2);
515 assert_eq!(cell1.sub_entity(ReferenceCellType::Triangle, 0), 0);
516
517 let edge0 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 0);
518 assert_eq!(edge0.sub_entity(ReferenceCellType::Point, 0), 0);
519 assert_eq!(edge0.sub_entity(ReferenceCellType::Point, 1), 1);
520 assert_eq!(edge0.sub_entity(ReferenceCellType::Interval, 0), 0);
521 let edge1 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 1);
522 assert_eq!(edge1.sub_entity(ReferenceCellType::Point, 0), 0);
523 assert_eq!(edge1.sub_entity(ReferenceCellType::Point, 1), 2);
524 assert_eq!(edge1.sub_entity(ReferenceCellType::Interval, 0), 1);
525 let edge2 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 2);
526 assert_eq!(edge2.sub_entity(ReferenceCellType::Point, 0), 1);
527 assert_eq!(edge2.sub_entity(ReferenceCellType::Point, 1), 3);
528 assert_eq!(edge2.sub_entity(ReferenceCellType::Interval, 0), 2);
529 let edge3 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 3);
530 assert_eq!(edge3.sub_entity(ReferenceCellType::Point, 0), 2);
531 assert_eq!(edge3.sub_entity(ReferenceCellType::Point, 1), 3);
532 assert_eq!(edge3.sub_entity(ReferenceCellType::Interval, 0), 3);
533 let edge4 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 4);
534 assert_eq!(edge4.sub_entity(ReferenceCellType::Point, 0), 3);
535 assert_eq!(edge4.sub_entity(ReferenceCellType::Point, 1), 4);
536 assert_eq!(edge4.sub_entity(ReferenceCellType::Interval, 0), 4);
537 let edge5 = MixedEntityTopology::new(&t, ReferenceCellType::Interval, 5);
538 assert_eq!(edge5.sub_entity(ReferenceCellType::Point, 0), 1);
539 assert_eq!(edge5.sub_entity(ReferenceCellType::Point, 1), 4);
540 assert_eq!(edge5.sub_entity(ReferenceCellType::Interval, 0), 5);
541
542 let vertex0 = MixedEntityTopology::new(&t, ReferenceCellType::Point, 0);
543 assert_eq!(vertex0.sub_entity(ReferenceCellType::Point, 0), 0);
544 let vertex1 = MixedEntityTopology::new(&t, ReferenceCellType::Point, 1);
545 assert_eq!(vertex1.sub_entity(ReferenceCellType::Point, 0), 1);
546 let vertex2 = MixedEntityTopology::new(&t, ReferenceCellType::Point, 2);
547 assert_eq!(vertex2.sub_entity(ReferenceCellType::Point, 0), 2);
548 let vertex3 = MixedEntityTopology::new(&t, ReferenceCellType::Point, 3);
549 assert_eq!(vertex3.sub_entity(ReferenceCellType::Point, 0), 3);
550 let vertex4 = MixedEntityTopology::new(&t, ReferenceCellType::Point, 4);
551 assert_eq!(vertex4.sub_entity(ReferenceCellType::Point, 0), 4);
552 }
553}