1use std::array;
2
3use crate::geometry::{ActiveCellId, IndexSpace};
4
5use crate::image::ImageRef;
6use crate::{mesh::Mesh, shared::SharedSlice};
7
8impl<const N: usize> Mesh<N> {
9 pub fn refine_flags(&self) -> &[bool] {
11 self.refine_flags.as_slice()
12 }
13 pub fn coarsen_flags(&self) -> &[bool] {
15 self.coarsen_flags.as_slice()
16 }
17
18 pub fn regrid(&mut self) {
20 self.regrid_map.clear();
21
22 self.old_blocks.clone_from(&self.blocks);
24
25 self.old_cell_splits.clear();
26 self.old_cell_splits.extend(
27 self.tree
28 .active_cell_indices()
29 .flat_map(|cell| self.tree.most_recent_active_split(cell)),
30 );
31
32 self.regrid_map
34 .resize(self.tree.num_active_cells(), ActiveCellId(0));
35
36 let mut coarsen_map = vec![ActiveCellId(0); self.tree.num_active_cells()];
37 self.tree
38 .coarsen_active_index_map(&self.coarsen_flags, &mut coarsen_map);
39
40 debug_assert!(self.tree.check_coarsen_flags(&self.coarsen_flags));
41 self.tree.coarsen(&self.coarsen_flags);
42
43 let mut refine_map = vec![ActiveCellId(0); self.tree.num_active_cells()];
44 let mut flags = vec![false; self.tree.num_active_cells()];
45
46 for (old, &new) in coarsen_map.iter().enumerate() {
47 flags[new.0] = self.refine_flags[old];
48 }
49
50 self.tree.refine_active_index_map(&flags, &mut refine_map);
51
52 debug_assert!(self.tree.check_refine_flags(&flags));
53 self.tree.refine(&flags);
54
55 for i in 0..self.regrid_map.len() {
56 self.regrid_map[i] = refine_map[coarsen_map[i].0];
57 }
58
59 self.build();
61 }
62
63 pub fn refine_global(&mut self) {
65 self.refine_flags.fill(true);
66 self.regrid();
67 }
68
69 pub fn refine_innermost(&mut self) {
71 let mut temp_rflags = vec![false; self.tree().num_active_cells()];
72 let mut cell_inner_index = 0;
74 let mut cell_inner_center = f64::MAX;
75 for cell in self.tree().active_cell_indices() {
76 let cell_bounds = self.tree().active_bounds(cell);
77 let cell_center = cell_bounds.center()[0]; if cell_center < cell_inner_center {
79 cell_inner_center = cell_center;
80 cell_inner_index = cell.0;
81 }
82 }
83 temp_rflags[cell_inner_index] = true;
85 self.refine_flags = temp_rflags;
86 self.balance_flags();
87 self.regrid();
88 }
89
90 pub fn coarsen_innermost(&mut self) {
92 let mut temp_cflags = vec![false; self.tree().num_active_cells()];
93 let mut cell_inner_index = 0;
95 let mut cell_inner_center = f64::MAX;
96 for cell in self.tree().active_cell_indices() {
97 let cell_bounds = self.tree().active_bounds(cell);
98 let cell_center = cell_bounds.center()[0]; if cell_center < cell_inner_center {
100 cell_inner_center = cell_center;
101 cell_inner_index = cell.0;
102 }
103 }
104 temp_cflags[cell_inner_index] = true;
106 self.coarsen_flags = temp_cflags;
107 self.balance_flags();
108 self.regrid();
109 }
110
111 pub fn regrid_in_radius(&mut self, radius: f64, fgl: usize) {
113 self.refine_flags.fill(false);
115 self.coarsen_flags.fill(false);
116 let mut temp_rflags = vec![false; self.tree().num_active_cells()];
117 let mut temp_cflags = vec![false; self.tree().num_active_cells()];
118 for cell in self.tree().active_cell_indices() {
119 let cell_bounds = self.tree().active_bounds(cell);
121 let cell_center = cell_bounds.center()[0]; let cell_level = self.tree().active_level(cell);
123 let cell_index = cell.0;
124 if cell_center < radius {
126 if cell_level < fgl {
127 temp_rflags[cell_index] = true;
128 }
129 if cell_level > fgl {
130 temp_cflags[cell_index] = true;
131 }
132 }
133 }
134 self.refine_flags = temp_rflags;
136 self.coarsen_flags = temp_cflags;
137 self.balance_flags();
139 self.regrid();
140 }
141
142 pub fn flag_wavelets(&mut self, order: usize, lower: f64, upper: f64, data: ImageRef) {
146 let buffer = 2 * (self.ghost / 2);
147 let support = (self.width + 2 * buffer) / 2;
148
149 assert!(order % 2 == 0);
150 assert!(order <= support);
151 assert_eq!(data.num_nodes(), self.num_nodes());
155
156 let element = self.request_element(support, order);
157 let element_coarse = self.request_element(self.width / 2, order / 2);
158
159 let support = element.support_refined();
160
161 let mut rflags_buf = std::mem::take(&mut self.refine_flags);
162 let mut cflags_buf = std::mem::take(&mut self.coarsen_flags);
163
164 let rflags = SharedSlice::new(&mut rflags_buf);
166 let cflags = SharedSlice::new(&mut cflags_buf);
167
168 self.block_compute(|mesh, store, block| {
169 let imsrc = store.scratch(support);
170 let imdest = store.scratch(support);
171
172 let nodes = mesh.block_nodes(block);
173 let space = mesh.block_space(block);
174
175 let block_system = data.slice(nodes.clone());
176
177 for &cell in mesh.blocks.active_cells(block) {
178 let is_cell_on_boundary = mesh.cell_needs_coarse_element(cell);
179
180 let window = if is_cell_on_boundary {
182 mesh.element_coarse_window(cell)
183 } else {
184 mesh.element_window(cell)
185 };
186
187 let mut should_refine = false;
188 let mut should_coarsen = true;
189
190 for field in data.channels() {
191 for (i, node) in window.iter().enumerate() {
193 imsrc[i] = block_system.channel(field)[space.index_from_node(node)];
194 }
195
196 if is_cell_on_boundary {
197 let src = &imsrc[..element_coarse.support_refined()];
198 let dst = &mut imdest[..element_coarse.support_refined()];
199
200 element_coarse.wavelet(src, dst);
201
202 for point in element_coarse.diagonal_points() {
203 should_refine = should_refine || dst[point].abs() >= upper;
204 should_coarsen = should_coarsen && dst[point].abs() <= lower;
205 }
206 } else {
207 element.wavelet(imsrc, imdest);
208
209 for point in element.diagonal_int_points(buffer) {
210 should_refine = should_refine || imdest[point].abs() >= upper;
211 should_coarsen = should_coarsen && imdest[point].abs() <= lower;
212 }
213 }
214
215 unsafe {
216 if should_refine {
217 *rflags.get_mut(cell.0) = true;
218 }
219 }
220
221 unsafe {
222 *cflags.get_mut(cell.0) = should_coarsen;
223 }
224 }
225 }
226 });
227
228 let _ = std::mem::replace(&mut self.refine_flags, rflags_buf);
229 let _ = std::mem::replace(&mut self.coarsen_flags, cflags_buf);
230
231 self.replace_element(element);
232 self.replace_element(element_coarse);
233 }
234
235 pub fn flags_debug(&mut self, debug: &mut [i64]) {
237 assert!(debug.len() == self.num_nodes());
238
239 let debug = SharedSlice::new(debug);
240
241 self.block_compute(|mesh, _, block| {
242 let block_nodes = mesh.block_nodes(block);
243 let block_space = mesh.block_space(block);
244 let block_size = mesh.blocks.size(block);
245 let cells = mesh.blocks.active_cells(block);
246
247 for (i, position) in IndexSpace::new(block_size).iter().enumerate() {
248 let cell = cells[i];
249 let origin: [_; N] = array::from_fn(|axis| (position[axis] * mesh.width) as isize);
250
251 for offset in IndexSpace::new([mesh.width + 1; N]).iter() {
252 let node = array::from_fn(|axis| origin[axis] + offset[axis] as isize);
253
254 let idx = block_nodes.start + block_space.index_from_node(node);
255
256 unsafe {
257 *debug.get_mut(idx) = mesh.refine_flags[cell.0] as i64;
258 }
259 }
260 }
261 });
262 }
263
264 pub fn set_refine_flag(&mut self, cell: usize) {
266 self.refine_flags[cell] = true
267 }
268
269 pub fn set_coarsen_flag(&mut self, cell: usize) {
271 self.coarsen_flags[cell] = true
272 }
273
274 pub fn buffer_refine_flags(&mut self, count: usize) {
276 for _ in 0..count {
277 for cell in self.tree.active_cell_indices() {
278 if !self.refine_flags[cell.0] {
279 continue;
280 }
281
282 for neighbor in self.tree.active_neighborhood(cell) {
283 self.refine_flags[neighbor.0] = true;
284 }
285 }
286 }
287 }
288
289 pub fn limit_level_range_flags(&mut self, min_level: usize, max_level: usize) {
292 assert!(self.refine_flags.len() == self.num_active_cells());
293 assert!(self.coarsen_flags.len() == self.num_active_cells());
294
295 for cell in self.tree.active_cell_indices() {
296 let level = self.tree.active_level(cell);
297 if level >= max_level {
298 self.refine_flags[cell.0] = false;
299 }
300
301 if level <= min_level {
302 self.coarsen_flags[cell.0] = false;
303 }
304 }
305 }
306
307 pub fn balance_flags(&mut self) {
311 self.tree.balance_refine_flags(&mut self.refine_flags);
313 for cell in self.tree.active_cell_indices() {
316 if self.refine_flags[cell.0] {
317 let level = self.tree.active_level(cell);
318 for neighbor in self.tree.active_neighborhood(cell) {
319 let nlevel = self.tree.active_level(neighbor);
320 if nlevel <= level {
321 self.coarsen_flags[neighbor.0] = false;
322 }
323 }
324 }
325 }
326 self.tree.balance_coarsen_flags(&mut self.coarsen_flags);
328 }
329
330 pub fn requires_regridding(&self) -> bool {
333 self.refine_flags.iter().any(|&b| b) || self.coarsen_flags.iter().any(|&b| b)
334 }
335
336 pub fn num_refine_cells(&self) -> usize {
338 self.refine_flags.iter().filter(|&&b| b).count()
339 }
340
341 pub fn num_coarsen_cells(&self) -> usize {
343 self.coarsen_flags.iter().filter(|&&b| b).count()
344 }
345}
346
347#[cfg(test)]
348mod tests {
349 use crate::geometry::{ActiveCellId, FaceArray, HyperBox};
350 use crate::kernel::BoundaryClass;
351 use crate::mesh::Mesh;
352
353 #[test]
354 fn element_windows() {
355 let mut mesh = Mesh::new(
356 HyperBox::UNIT,
357 4,
358 2,
359 FaceArray::from_sides([BoundaryClass::Ghost; 2], [BoundaryClass::OneSided; 2]),
360 );
361 mesh.refine_global();
362
363 mesh.set_refine_flag(0);
364 mesh.regrid();
365
366 assert!(!mesh.cell_needs_coarse_element(ActiveCellId(0)));
367 assert!(!mesh.cell_needs_coarse_element(ActiveCellId(1)));
368 assert!(!mesh.cell_needs_coarse_element(ActiveCellId(2)));
369 assert!(!mesh.cell_needs_coarse_element(ActiveCellId(3)));
370 assert!(mesh.cell_needs_coarse_element(ActiveCellId(4)));
371 assert!(mesh.cell_needs_coarse_element(ActiveCellId(5)));
372 assert!(mesh.cell_needs_coarse_element(ActiveCellId(6)));
373 }
374}