1use std::{array, ops::Range};
2
3use super::{ActiveCellId, Tree};
4use crate::geometry::{Face, FaceMask, HyperBox, IndexSpace};
5use bitvec::prelude::*;
6use datasize::DataSize;
7
8#[derive(
9 Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, serde::Serialize, serde::Deserialize,
10)]
11pub struct BlockId(pub usize);
12
13#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
15pub struct TreeBlocks<const N: usize> {
16 #[serde(with = "crate::array::vec")]
18 active_cell_positions: Vec<[usize; N]>,
19 active_cell_to_block: Vec<usize>,
21 #[serde(with = "crate::array::vec")]
23 block_sizes: Vec<[usize; N]>,
24 block_active_indices: Vec<ActiveCellId>,
27 block_active_offsets: Vec<usize>,
29 block_bounds: Vec<HyperBox<N>>,
31 block_levels: Vec<usize>,
33 boundaries: BitVec,
35 #[serde(with = "crate::array")]
37 width: [usize; N],
38 ghost: usize,
40 offsets: Vec<usize>,
42}
43
44impl<const N: usize> TreeBlocks<N> {
45 pub fn new(width: [usize; N], ghost: usize) -> Self {
46 Self {
47 active_cell_positions: Default::default(),
48 active_cell_to_block: Default::default(),
49 block_sizes: Default::default(),
50 block_active_indices: Default::default(),
51 block_active_offsets: Default::default(),
52 block_bounds: Default::default(),
53 block_levels: Default::default(),
54 boundaries: Default::default(),
55 width,
56 ghost,
57 offsets: Default::default(),
58 }
59 }
60
61 pub fn build(&mut self, tree: &Tree<N>) {
64 self.build_blocks(tree);
65 self.build_bounds(tree);
66 self.build_boundaries(tree);
67 self.build_levels(tree);
68 self.build_nodes();
69 }
70
71 pub fn len(&self) -> usize {
73 self.block_sizes.len()
74 }
75
76 pub fn indices(&self) -> impl Iterator<Item = BlockId> + use<N> {
77 (0..self.len()).map(BlockId)
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.len() == 0
82 }
83
84 pub fn active_cells(&self, block: BlockId) -> &[ActiveCellId] {
86 &self.block_active_indices
87 [self.block_active_offsets[block.0]..self.block_active_offsets[block.0 + 1]]
88 }
89
90 pub fn size(&self, block: BlockId) -> [usize; N] {
92 self.block_sizes[block.0]
93 }
94
95 pub fn node_size(&self, block: BlockId) -> [usize; N] {
97 array::from_fn(|axis| self.block_sizes[block.0][axis] * self.width[axis] + 1)
98 }
99
100 pub fn bounds(&self, block: BlockId) -> HyperBox<N> {
102 self.block_bounds[block.0]
103 }
104
105 pub fn level(&self, block: BlockId) -> usize {
107 self.block_levels[block.0]
108 }
109
110 pub fn boundary_flags(&self, block: BlockId) -> FaceMask<N> {
112 let mut flags = [[false; 2]; N];
113
114 for face in Face::<N>::iterate() {
115 flags[face.axis][face.side as usize] =
116 self.boundaries[block.0 * 2 * N + face.to_linear()];
117 }
118
119 FaceMask::pack(flags)
120 }
121
122 pub fn active_cell_position(&self, cell: ActiveCellId) -> [usize; N] {
124 self.active_cell_positions[cell.0]
125 }
126
127 pub fn active_cell_block(&self, cell: ActiveCellId) -> BlockId {
129 BlockId(self.active_cell_to_block[cell.0])
130 }
131
132 pub fn width(&self) -> [usize; N] {
134 self.width
135 }
136
137 pub fn ghost(&self) -> usize {
139 self.ghost
140 }
141
142 pub fn num_nodes(&self) -> usize {
154 *self.offsets.last().unwrap()
155 }
156
157 pub fn nodes(&self, block: BlockId) -> Range<usize> {
159 self.offsets[block.0]..self.offsets[block.0 + 1]
160 }
161
162 fn build_blocks(&mut self, tree: &Tree<N>) {
163 let num_active_cells = tree.num_active_cells();
164
165 self.active_cell_positions.resize(num_active_cells, [0; N]);
167 self.active_cell_positions.fill([0; N]);
168
169 self.active_cell_to_block
170 .resize(num_active_cells, usize::MAX);
171 self.active_cell_to_block.fill(usize::MAX);
172
173 self.block_sizes.clear();
174 self.block_active_indices.clear();
175 self.block_active_offsets.clear();
176
177 for active in tree.active_cell_indices() {
179 if self.active_cell_to_block[active.0] != usize::MAX {
180 continue;
182 }
183
184 let block = self.block_sizes.len();
186
187 self.active_cell_positions[active.0] = [0; N];
188 self.active_cell_to_block[active.0] = block;
189
190 self.block_sizes.push([1; N]);
191 let block_cell_offset = self.block_active_indices.len();
192
193 self.block_active_offsets.push(block_cell_offset);
194 self.block_active_indices.push(active);
195
196 for axis in 0..N {
198 'expand: loop {
200 let face = Face::<N>::positive(axis);
201
202 let size = self.block_sizes[block];
203 let space = IndexSpace::new(size);
204
205 for index in space.face_window(Face::positive(axis)).iter() {
207 let cell = tree.cell_from_active_index(
209 self.block_active_indices
210 [block_cell_offset + space.linear_from_cartesian(index)],
211 );
212 let level = tree.level(cell);
213 let Some(neighbor) = tree.neighbor(cell, face) else {
219 break 'expand;
220 };
221
222 if tree.is_boundary_face(cell, face) {
223 break 'expand;
224 }
225
226 if level != tree.level(neighbor) || !tree.is_active(neighbor) {
227 break 'expand;
228 }
229
230 if self.active_cell_to_block
231 [tree.active_index_from_cell(neighbor).unwrap().0]
232 != usize::MAX
233 {
234 break 'expand;
235 }
236 }
237
238 for index in space.face_window(Face::positive(axis)).iter() {
240 let active = self.block_active_indices
241 [block_cell_offset + space.linear_from_cartesian(index)];
242
243 let cell = tree.cell_from_active_index(active);
244 let cell_neighbor = tree.neighbor(cell, face).unwrap();
245 debug_assert!(tree.is_active(cell_neighbor));
246 let active_neighbor = tree.active_index_from_cell(cell_neighbor).unwrap();
247
248 self.active_cell_positions[active_neighbor.0] = index;
249 self.active_cell_positions[active_neighbor.0][axis] += 1;
250 self.active_cell_to_block[active_neighbor.0] = block;
251
252 self.block_active_indices.push(active_neighbor);
253 }
254
255 self.block_sizes[block][axis] += 1;
256 }
257 }
258 }
259
260 self.block_active_offsets
261 .push(self.block_active_indices.len());
262 }
263
264 fn build_bounds(&mut self, tree: &Tree<N>) {
265 self.block_bounds.clear();
266
267 for block in self.indices() {
268 let size = self.size(block);
269 let a = *self.active_cells(block).first().unwrap();
270
271 let cell_bounds = tree.bounds(tree.cell_from_active_index(a));
272
273 self.block_bounds.push(HyperBox {
274 origin: cell_bounds.origin,
275 size: array::from_fn(|axis| cell_bounds.size[axis] * size[axis] as f64),
276 })
277 }
278 }
279
280 fn build_boundaries(&mut self, tree: &Tree<N>) {
281 self.boundaries.clear();
282
283 for block in self.indices() {
284 let a = 0;
285 let b: usize = self.active_cells(block).len() - 1;
286
287 for face in Face::<N>::iterate() {
288 let active = if face.side {
289 self.active_cells(block)[b]
290 } else {
291 self.active_cells(block)[a]
292 };
293 let cell = tree.cell_from_active_index(active);
294 self.boundaries.push(tree.is_boundary_face(cell, face))
295 }
296 }
297 }
298
299 fn build_levels(&mut self, tree: &Tree<N>) {
300 self.block_levels.resize(self.len(), 0);
301 for block in self.indices() {
302 let active = self.active_cells(block)[0];
303 self.block_levels[block.0] = tree.active_level(active);
304 }
305 }
306
307 fn build_nodes(&mut self) {
308 for axis in 0..N {
309 assert!(self.width[axis] % 2 == 0);
310 }
311
312 self.offsets.clear();
314 self.offsets.reserve(self.len() + 1);
315
316 let mut cursor = 0;
318 self.offsets.push(cursor);
319
320 for block in self.indices() {
321 let size = self.size(block);
322 let block_width: [usize; N] =
324 array::from_fn(|axis| self.width[axis] * size[axis] + 1 + 2 * self.ghost);
325
326 cursor += block_width.iter().product::<usize>();
327 self.offsets.push(cursor);
328 }
329 }
330}
331
332impl<const N: usize> DataSize for TreeBlocks<N> {
333 const IS_DYNAMIC: bool = true;
334 const STATIC_HEAP_SIZE: usize = 0;
335
336 fn estimate_heap_size(&self) -> usize {
337 self.active_cell_positions.estimate_heap_size()
338 + self.active_cell_to_block.estimate_heap_size()
339 + self.block_sizes.estimate_heap_size()
340 + self.block_active_offsets.estimate_heap_size()
341 + self.block_active_indices.estimate_heap_size()
342 + self.block_bounds.estimate_heap_size()
343 + self.block_levels.estimate_heap_size()
344 + self.boundaries.capacity() / size_of::<usize>()
345 + self.offsets.estimate_heap_size()
346 }
347}
348
349#[cfg(test)]
350mod tests {
351 use super::*;
352 use crate::{geometry::Tree, prelude::HyperBox};
353
354 #[test]
355 fn greedy_meshing() {
356 let mut tree = Tree::new(HyperBox::<2>::UNIT);
357 tree.refine(&[true]);
358 tree.refine(&[true, false, false, false]);
359
360 let mut blocks = TreeBlocks::new([4; 2], 2);
361 blocks.build(&tree);
362
363 assert!(blocks.len() == 3);
364 assert_eq!(blocks.level(BlockId(0)), 2);
365 assert_eq!(blocks.size(BlockId(0)), [2, 2]);
366 assert_eq!(
367 blocks.active_cells(BlockId(0)),
368 [
369 ActiveCellId(0),
370 ActiveCellId(1),
371 ActiveCellId(2),
372 ActiveCellId(3)
373 ]
374 );
375 assert_eq!(blocks.level(BlockId(1)), 1);
376 assert_eq!(blocks.size(BlockId(1)), [1, 2]);
377 assert_eq!(
378 blocks.active_cells(BlockId(1)),
379 [ActiveCellId(4), ActiveCellId(6),]
380 );
381 assert_eq!(blocks.level(BlockId(2)), 1);
382 assert_eq!(blocks.size(BlockId(2)), [1, 1]);
383 assert_eq!(blocks.active_cells(BlockId(2)), [ActiveCellId(5)]);
384
385 tree.refine(&[false, false, false, false, true, false, false]);
386 blocks.build(&tree);
387 assert!(blocks.len() == 2);
388 assert_eq!(blocks.level(BlockId(0)), 2);
389 assert_eq!(blocks.size(BlockId(0)), [4, 2]);
390 assert_eq!(
391 blocks.active_cells(BlockId(0)),
392 [
393 ActiveCellId(0),
394 ActiveCellId(1),
395 ActiveCellId(4),
396 ActiveCellId(5),
397 ActiveCellId(2),
398 ActiveCellId(3),
399 ActiveCellId(6),
400 ActiveCellId(7),
401 ]
402 );
403 assert_eq!(blocks.level(BlockId(1)), 1);
404 assert_eq!(blocks.size(BlockId(1)), [2, 1]);
405 assert_eq!(
406 blocks.active_cells(BlockId(1)),
407 [ActiveCellId(8), ActiveCellId(9),]
408 );
409 }
410
411 #[test]
412 fn node_ranges() {
413 let mut tree = Tree::new(HyperBox::<2>::UNIT);
414 let mut blocks = TreeBlocks::new([8; 2], 3);
415 tree.refine(&[true]);
416 tree.refine(&[true, false, false, false]);
417 tree.build();
418
419 blocks.build(&tree);
420
421 assert_eq!(blocks.len(), 3);
422
423 assert_eq!(blocks.nodes(BlockId(0)), 0..529);
424 assert_eq!(blocks.nodes(BlockId(1)), 529..874);
425 assert_eq!(blocks.nodes(BlockId(2)), 874..1099);
426 }
427}