1use super::{blocks::BlockId, *};
2
3#[derive(
4 Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, serde::Serialize, serde::Deserialize,
5)]
6pub struct NeighborId(pub usize);
7
8#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
10pub struct TreeCellNeighbor<const N: usize> {
11 pub cell: ActiveCellId,
13 pub neighbor: ActiveCellId,
15 pub region: Region<N>,
17 pub boundary_region: Region<N>,
19}
20
21#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
23pub struct TreeBlockNeighbor<const N: usize> {
24 pub block: BlockId,
26 pub neighbor: BlockId,
28 pub a: TreeCellNeighbor<N>,
30 pub b: TreeCellNeighbor<N>,
32}
33
34impl<const N: usize> DataSize for TreeBlockNeighbor<N> {
35 const IS_DYNAMIC: bool = false;
36 const STATIC_HEAP_SIZE: usize = 0;
37
38 fn estimate_heap_size(&self) -> usize {
39 0
40 }
41}
42
43impl<const N: usize> TreeBlockNeighbor<N> {
44 pub fn face(&self) -> Option<Face<N>> {
46 regions_to_face(self.a.region, self.b.region)
47 }
48}
49
50fn regions_to_face<const N: usize>(a: Region<N>, b: Region<N>) -> Option<Face<N>> {
51 let mut adjacency = 0;
52 let mut faxis = 0;
53 let mut fside = false;
54
55 for axis in 0..N {
56 let aside = a.side(axis);
57 let bside = b.side(axis);
58
59 if aside == bside && aside != Side::Middle {
60 adjacency += 1;
61 faxis = axis;
62 fside = aside == Side::Right;
63 }
64 }
65
66 if adjacency == 1 {
67 Some(Face {
68 axis: faxis,
69 side: fside,
70 })
71 } else {
72 None
73 }
74}
75
76#[derive(Default, Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
78pub struct TreeNeighbors<const N: usize> {
79 neighbors: Vec<TreeBlockNeighbor<N>>,
81 block_offsets: Vec<usize>,
83 fine: Vec<usize>,
85 direct: Vec<usize>,
87 coarse: Vec<usize>,
89}
90
91impl<const N: usize> TreeNeighbors<N> {
92 pub fn fine(&self) -> impl Iterator<Item = &TreeBlockNeighbor<N>> {
94 self.fine.iter().map(|&i| &self.neighbors[i])
95 }
96
97 pub fn direct(&self) -> impl Iterator<Item = &TreeBlockNeighbor<N>> {
99 self.direct.iter().map(|&i| &self.neighbors[i])
100 }
101
102 pub fn coarse(&self) -> impl Iterator<Item = &TreeBlockNeighbor<N>> {
104 self.coarse.iter().map(|&i| &self.neighbors[i])
105 }
106
107 pub fn iter(&self) -> slice::Iter<'_, TreeBlockNeighbor<N>> {
109 self.neighbors.iter()
110 }
111
112 pub fn indices(&self) -> impl Iterator<Item = NeighborId> {
113 (0..self.neighbors.len()).map(NeighborId)
114 }
115
116 pub fn fine_indices(&self) -> impl Iterator<Item = NeighborId> + '_ {
117 self.fine.iter().copied().map(NeighborId)
118 }
119
120 pub fn direct_indices(&self) -> impl Iterator<Item = NeighborId> + '_ {
121 self.direct.iter().copied().map(NeighborId)
122 }
123
124 pub fn coarse_indices(&self) -> impl Iterator<Item = NeighborId> + '_ {
125 self.coarse.iter().copied().map(NeighborId)
126 }
127
128 pub fn block(&self, block: BlockId) -> slice::Iter<'_, TreeBlockNeighbor<N>> {
130 self.neighbors[self.block_offsets[block.0]..self.block_offsets[block.0 + 1]].iter()
131 }
132
133 pub fn block_range(&self, block: BlockId) -> Range<usize> {
135 self.block_offsets[block.0]..self.block_offsets[block.0 + 1]
136 }
137
138 pub fn neighbor(&self, idx: NeighborId) -> &TreeBlockNeighbor<N> {
139 &self.neighbors[idx.0]
140 }
141
142 pub fn build(&mut self, tree: &Tree<N>, blocks: &TreeBlocks<N>) {
144 self.neighbors.clear();
145 self.block_offsets.clear();
146 self.fine.clear();
147 self.coarse.clear();
148 self.direct.clear();
149
150 let mut neighbors = Vec::new();
152
153 for block in blocks.indices() {
154 self.block_offsets.push(self.neighbors.len());
155
156 neighbors.clear();
158 Self::build_cell_neighbors(tree, blocks, block, &mut neighbors);
159
160 neighbors.sort_unstable_by(|left, right| {
162 let lblock = blocks.active_cell_block(left.neighbor);
163 let rblock = blocks.active_cell_block(right.neighbor);
164
165 left.boundary_region
166 .cmp(&right.boundary_region)
167 .then(lblock.cmp(&rblock))
168 .then(left.neighbor.cmp(&right.neighbor))
169 .then(left.cell.cmp(&right.cell))
170 .then(left.region.cmp(&right.region))
171 });
172
173 Self::taverse_cell_neighbors(blocks, &mut neighbors, |neighbor, a, b| {
174 let acell = tree.cell_from_active_index(a.cell);
175 let aneighbor = tree.cell_from_active_index(a.neighbor);
176
177 let kind = InterfaceKind::from_levels(tree.level(acell), tree.level(aneighbor));
179 let interface = TreeBlockNeighbor {
180 block,
181 neighbor,
182 a,
183 b,
184 };
185
186 let idx = self.neighbors.len();
187 self.neighbors.push(interface);
188
189 match kind {
190 InterfaceKind::Fine => self.fine.push(idx),
191 InterfaceKind::Direct => self.direct.push(idx),
192 InterfaceKind::Coarse => self.coarse.push(idx),
193 }
194 });
195 }
196
197 self.block_offsets.push(self.neighbors.len());
198 }
199
200 fn build_cell_neighbors(
202 tree: &Tree<N>,
203 blocks: &TreeBlocks<N>,
204 block: BlockId,
205 neighbors: &mut Vec<TreeCellNeighbor<N>>,
206 ) {
207 let block_size = blocks.size(block);
208 let block_active_cells = blocks.active_cells(block);
209 let block_space = IndexSpace::new(block_size);
210
211 debug_assert!(block_size.iter().product::<usize>() == block_active_cells.len());
212
213 for region in regions::<N>() {
214 if region == Region::CENTRAL {
215 continue;
216 }
217
218 for index in block_space.region_adjacent_window(region) {
220 let active = block_active_cells[block_space.linear_from_cartesian(index)];
221 let cell = tree.cell_from_active_index(active);
222 let periodic = tree.boundary_region(cell, region);
223
224 for neighbor in tree.active_neighbors_in_region(cell, region) {
225 neighbors.push(TreeCellNeighbor {
226 cell: active,
227 neighbor,
228 region,
229 boundary_region: periodic,
230 })
231 }
232 }
233 }
234 }
235
236 fn taverse_cell_neighbors(
238 blocks: &TreeBlocks<N>,
239 neighbors: &mut [TreeCellNeighbor<N>],
240 mut f: impl FnMut(BlockId, TreeCellNeighbor<N>, TreeCellNeighbor<N>),
241 ) {
242 let mut neighbors = neighbors.iter().cloned().peekable();
243
244 while let Some(a) = neighbors.next() {
245 let neighbor = blocks.active_cell_block(a.neighbor);
246
247 let mut b = a.clone();
249
250 loop {
251 if let Some(next) = neighbors.peek() {
252 if a.boundary_region == next.boundary_region
253 && neighbor == blocks.active_cell_block(next.neighbor)
254 {
255 b = neighbors.next().unwrap();
256 continue;
257 }
258 }
259
260 break;
261 }
262
263 f(neighbor, a, b)
264 }
265 }
266}
267
268impl<const N: usize> DataSize for TreeNeighbors<N> {
269 const IS_DYNAMIC: bool = true;
270 const STATIC_HEAP_SIZE: usize = 0;
271
272 fn estimate_heap_size(&self) -> usize {
273 self.neighbors.estimate_heap_size()
274 + self.block_offsets.estimate_heap_size()
275 + self.fine.estimate_heap_size()
276 + self.direct.estimate_heap_size()
277 + self.coarse.estimate_heap_size()
278 }
279}
280
281#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
282enum InterfaceKind {
283 Coarse,
284 Direct,
285 Fine,
286}
287
288impl InterfaceKind {
289 fn from_levels(level: usize, neighbor: usize) -> Self {
290 match level as isize - neighbor as isize {
291 1 => InterfaceKind::Coarse,
292 0 => InterfaceKind::Direct,
293 -1 => InterfaceKind::Fine,
294 _ => panic!("Unbalanced levels"),
295 }
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302 use crate::geometry::HyperBox;
303
304 #[test]
305 fn regions_and_faces() {
306 assert_eq!(regions_to_face::<2>(Region::CENTRAL, Region::CENTRAL), None);
307 assert_eq!(
308 regions_to_face(
309 Region::new([Side::Left, Side::Middle]),
310 Region::new([Side::Left, Side::Left])
311 ),
312 Some(Face::negative(0))
313 );
314 assert_eq!(
315 regions_to_face(
316 Region::new([Side::Left, Side::Right]),
317 Region::new([Side::Left, Side::Right])
318 ),
319 None
320 );
321 assert_eq!(
322 regions_to_face(
323 Region::new([Side::Left, Side::Right]),
324 Region::new([Side::Middle, Side::Right])
325 ),
326 Some(Face::positive(1))
327 );
328 assert_eq!(
329 regions_to_face(
330 Region::new([Side::Middle, Side::Right]),
331 Region::new([Side::Middle, Side::Right])
332 ),
333 Some(Face::positive(1))
334 );
335 }
336
337 #[test]
338 fn neighbors() {
339 let mut tree = Tree::new(HyperBox::<2>::UNIT);
340 let mut blocks = TreeBlocks::new([4; 2], 2);
341 let mut interfaces = TreeNeighbors::default();
342 tree.refine(&[true]);
343 tree.refine(&[true, false, false, false]);
344 blocks.build(&tree);
345 interfaces.build(&tree, &blocks);
346
347 let mut coarse = interfaces.coarse();
348
349 assert_eq!(
350 coarse.next(),
351 Some(&TreeBlockNeighbor {
352 block: BlockId(0),
353 neighbor: BlockId(1),
354 a: TreeCellNeighbor {
355 cell: ActiveCellId(1),
356 neighbor: ActiveCellId(4),
357 region: Region::new([Side::Right, Side::Middle]),
358 boundary_region: Region::CENTRAL,
359 },
360 b: TreeCellNeighbor {
361 cell: ActiveCellId(3),
362 neighbor: ActiveCellId(6),
363 region: Region::new([Side::Right, Side::Right]),
364 boundary_region: Region::CENTRAL,
365 }
366 })
367 );
368
369 assert_eq!(
370 coarse.next(),
371 Some(&TreeBlockNeighbor {
372 block: BlockId(0),
373 neighbor: BlockId(2),
374 a: TreeCellNeighbor {
375 cell: ActiveCellId(2),
376 neighbor: ActiveCellId(5),
377 region: Region::new([Side::Middle, Side::Right]),
378 boundary_region: Region::CENTRAL,
379 },
380 b: TreeCellNeighbor {
381 cell: ActiveCellId(3),
382 neighbor: ActiveCellId(5),
383 region: Region::new([Side::Middle, Side::Right]),
384 boundary_region: Region::CENTRAL,
385 }
386 })
387 );
388 assert_eq!(coarse.next(), None);
389 }
390}