1use crate::geometry::{ActiveCellId, IndexSpace, NeighborId, Split};
2use crate::image::ImageShared;
3use crate::kernel::Interpolation;
4use rayon::iter::{ParallelBridge, ParallelIterator as _};
5use reborrow::ReborrowMut;
6use std::array;
7
8use crate::{
9 image::{ImageMut, ImageRef},
10 kernel::SystemBoundaryConds,
11 mesh::Mesh,
12 shared::SharedSlice,
13};
14
15impl<const N: usize> Mesh<N> {
16 pub fn transfer_system(&mut self, order: usize, source: ImageRef, dest: ImageMut) {
19 assert_eq!(source.num_channels(), dest.num_channels());
20 assert_eq!(dest.num_nodes(), self.num_nodes());
21 assert_eq!(source.num_nodes(), self.num_old_nodes());
22
23 match order {
24 2 => self.transfer_system_impl::<2>(source, dest),
25 4 => self.transfer_system_impl::<4>(source, dest),
26 6 => self.transfer_system_impl::<6>(source, dest),
27 _ => unimplemented!("Order unimplemented"),
28 }
29 }
30
31 fn transfer_system_impl<const ORDER: usize>(&mut self, source: ImageRef, dest: ImageMut) {
33 assert!(self.num_nodes() == dest.num_nodes());
34 assert!(self.num_old_nodes() == source.num_nodes());
35
36 let dest: ImageShared = dest.into();
37
38 self.old_block_compute(|mesh, _store, block| {
39 let size = mesh.old_blocks.size(block);
40 let level = mesh.old_block_level(block);
41 let nodes = mesh.old_block_nodes(block);
42 let space = mesh.old_block_space(block);
43
44 let block_source = source.slice(nodes.clone());
45
46 for (i, offset) in IndexSpace::new(size).iter().enumerate() {
47 let cell = mesh.old_blocks.active_cells(block)[i];
48 let cell_origin: [_; N] = array::from_fn(|axis| offset[axis] * mesh.width);
49
50 let new_cell = mesh.regrid_map[cell.0];
51 let new_level = mesh.tree.active_level(new_cell);
52
53 #[allow(clippy::comparison_chain)]
54 if new_level > level {
55 for child in Split::<N>::enumerate() {
57 let new_cell = ActiveCellId(new_cell.0 + child.to_linear());
59
60 let new_block = mesh.blocks.active_cell_block(new_cell);
61 let new_nodes = mesh.block_nodes(new_block);
62 let new_space = mesh.block_space(new_block);
63
64 let mut block_dest = unsafe { dest.slice_mut(new_nodes.clone()) };
65
66 let mut cell_origin: [_; N] = array::from_fn(|axis| 2 * cell_origin[axis]);
67
68 for axis in 0..N {
69 if child.is_set(axis) {
70 cell_origin[axis] += mesh.width;
71 }
72 }
73
74 let node_size = mesh.cell_node_size(new_cell);
75 let node_origin = mesh.active_node_origin(new_cell);
76
77 for node_offset in IndexSpace::new(node_size).iter() {
78 let source_node = array::from_fn(|axis| {
79 (cell_origin[axis] + node_offset[axis]) as isize
80 });
81 let dest_node = array::from_fn(|axis| {
82 (node_origin[axis] + node_offset[axis]) as isize
83 });
84
85 for field in dest.channels() {
86 let v = space.prolong(
87 Interpolation::<ORDER>,
88 source_node,
89 block_source.channel(field),
90 );
91 block_dest.channel_mut(field)
92 [new_space.index_from_node(dest_node)] = v;
93 }
94 }
95 }
96 } else if new_level == level {
97 let new_block = mesh.blocks.active_cell_block(new_cell);
99 let new_nodes = mesh.block_nodes(new_block);
100 let new_space = mesh.block_space(new_block);
101
102 let mut block_dest = unsafe { dest.slice_mut(new_nodes.clone()) };
103
104 let node_size = mesh.cell_node_size(new_cell);
105 let node_origin = mesh.active_node_origin(new_cell);
106
107 for node_offset in IndexSpace::new(node_size).iter() {
108 let source_node =
109 array::from_fn(|axis| (cell_origin[axis] + node_offset[axis]) as isize);
110 let dest_node =
111 array::from_fn(|axis| (node_origin[axis] + node_offset[axis]) as isize);
112
113 for field in dest.channels() {
114 let v = block_source.channel(field)[space.index_from_node(source_node)];
115 block_dest.channel_mut(field)[new_space.index_from_node(dest_node)] = v;
116 }
117 }
118 } else {
119 let split = mesh.old_cell_splits[cell.0];
121
122 let new_block = mesh.blocks.active_cell_block(new_cell);
123 let new_offset = mesh.blocks.active_cell_position(new_cell);
124 let new_size = mesh.blocks.size(new_block);
125 let new_nodes = mesh.block_nodes(new_block);
126 let new_space = mesh.block_space(new_block);
127
128 let mut block_dest = unsafe { dest.slice_mut(new_nodes.clone()) };
129
130 let cell_origin: [_; N] = array::from_fn(|axis| cell_origin[axis] / 2);
131
132 let mut node_size = [mesh.width / 2; N];
133
134 for axis in 0..N {
135 if new_offset[axis] == new_size[axis] - 1 && split.is_set(axis) {
136 node_size[axis] += 1;
137 }
138 }
139
140 let mut node_origin: [_; N] =
141 array::from_fn(|axis| new_offset[axis] * mesh.width);
142
143 for axis in 0..N {
144 if split.is_set(axis) {
145 node_origin[axis] += mesh.width / 2;
146 }
147 }
148
149 for node_offset in IndexSpace::new(node_size).iter() {
150 let source_node = array::from_fn(|axis| {
151 2 * (cell_origin[axis] + node_offset[axis]) as isize
152 });
153 let dest_node =
154 array::from_fn(|axis| (node_origin[axis] + node_offset[axis]) as isize);
155
156 for field in dest.channels() {
157 let v = block_source.channel(field)[space.index_from_node(source_node)];
158 block_dest.channel_mut(field)[new_space.index_from_node(dest_node)] = v;
159 }
160 }
161 }
162 }
163 });
164 }
165
166 pub fn fill_boundary<BCs: SystemBoundaryConds<N> + Sync>(
169 &mut self,
170 order: usize,
171 bcs: BCs,
172 system: ImageMut,
173 ) {
174 assert_eq!(system.num_nodes(), self.num_nodes());
175
176 self.fill_boundary_to_extent(order, self.ghost, bcs, system);
177 }
178
179 pub fn fill_boundary_to_extent<C: SystemBoundaryConds<N> + Sync>(
183 &mut self,
184 order: usize,
185 extent: usize,
186 bcs: C,
187 mut system: ImageMut,
188 ) {
189 assert_eq!(system.num_nodes(), self.num_nodes());
190 assert!(extent <= self.ghost);
191
192 self.fill_fine(extent, system.rb_mut());
193 self.fill_direct(extent, system.rb_mut());
194
195 self.fill_physical(extent, &bcs, system.rb_mut());
196 match order {
197 2 => self.fill_prolong::<2>(extent, system.rb_mut()),
198 4 => self.fill_prolong::<4>(extent, system.rb_mut()),
199 6 => self.fill_prolong::<6>(extent, system.rb_mut()),
200 _ => unimplemented!("Fill order not implemented"),
201 }
202 self.fill_physical(extent, &bcs, system.rb_mut());
203 }
204
205 fn fill_physical<C: SystemBoundaryConds<N> + Sync>(
207 &mut self,
208 extent: usize,
209 bcs: &C,
210 dest: ImageMut,
211 ) {
212 debug_assert!(dest.num_nodes() == self.num_nodes());
213
214 let shared: ImageShared = dest.into();
215
216 self.blocks.indices().par_bridge().for_each(|block| {
217 let nodes = self.block_nodes(block);
219 let space = self.block_space(block);
220 let bcs = self.block_bcs(block, bcs.clone());
221
222 let mut block_system = unsafe { shared.slice_mut(nodes) };
223
224 for field in shared.channels() {
225 space.fill_boundary(extent, bcs.field(field), block_system.channel_mut(field));
226 }
227 });
228 }
229
230 fn fill_direct(&mut self, extent: usize, result: ImageMut) {
232 let shared: ImageShared = result.into();
233
234 self.neighbors
236 .direct_indices()
237 .par_bridge()
238 .for_each(|interface| {
239 let info = self.interfaces.interface(interface);
240
241 let block_space = self.block_space(info.block);
242 let block_nodes = self.block_nodes(info.block);
243 let neighbor_space = self.block_space(info.neighbor);
244 let neighbor_nodes = self.block_nodes(info.neighbor);
245
246 let dest = info.dest;
247 let source = info.source;
248
249 let mut block_system = unsafe { shared.slice_mut(block_nodes) };
250 let neighbor_system = unsafe { shared.slice(neighbor_nodes) };
251
252 for node in self.interfaces.interface_nodes_active(interface, extent) {
253 let block_node = array::from_fn(|axis| node[axis] as isize + dest[axis]);
254 let neighbor_node = array::from_fn(|axis| node[axis] as isize + source[axis]);
255
256 let block_index = block_space.index_from_node(block_node);
257 let neighbor_index = neighbor_space.index_from_node(neighbor_node);
258
259 for field in shared.channels() {
260 let value = neighbor_system.channel(field)[neighbor_index];
261 block_system.channel_mut(field)[block_index] = value;
262 }
263 }
264 });
265 }
266
267 fn fill_fine(&mut self, extent: usize, result: ImageMut) {
269 let shared: ImageShared = result.into();
270
271 self.neighbors
272 .fine_indices()
273 .par_bridge()
274 .for_each(|interface| {
275 let info = self.interfaces.interface(interface);
276
277 let block_space = self.block_space(info.block);
278 let block_nodes = self.block_nodes(info.block);
279 let neighbor_space = self.block_space(info.neighbor);
280 let neighbor_nodes = self.block_nodes(info.neighbor);
281
282 let mut block_system = unsafe { shared.slice_mut(block_nodes) };
283 let neighbor_system = unsafe { shared.slice(neighbor_nodes) };
284
285 for node in self.interfaces.interface_nodes_active(interface, extent) {
286 let block_node = array::from_fn(|axis| node[axis] as isize + info.dest[axis]);
287 let neighbor_node =
288 array::from_fn(|axis| 2 * (node[axis] as isize + info.source[axis]));
289
290 let block_index = block_space.index_from_node(block_node);
291 let neighbor_index = neighbor_space.index_from_node(neighbor_node);
292
293 for field in shared.channels() {
294 let value = neighbor_system.channel(field)[neighbor_index];
295 block_system.channel_mut(field)[block_index] = value;
296 }
297 }
298 });
299 }
300
301 fn fill_prolong<const ORDER: usize>(&mut self, extent: usize, result: ImageMut) {
303 let shared: ImageShared = result.into();
304
305 self.neighbors
306 .coarse_indices()
307 .par_bridge()
308 .for_each(|interface| {
309 let info = self.interfaces.interface(interface);
310
311 let block_nodes = self.block_nodes(info.block);
312 let block_space = self.block_space(info.block);
313 let neighbor_nodes = self.block_nodes(info.neighbor);
314 let neighbor_space = self.block_space(info.neighbor);
315
316 let mut block_system = unsafe { shared.slice_mut(block_nodes) };
317 let neighbor_system = unsafe { shared.slice(neighbor_nodes) };
318
319 for node in self.interfaces.interface_nodes_active(interface, extent) {
320 let block_node = array::from_fn(|axis| node[axis] as isize + info.dest[axis]);
321
322 let neighbor_node =
323 array::from_fn(|axis| node[axis] as isize + info.source[axis]);
324 let block_index = block_space.index_from_node(block_node);
325
326 for field in shared.channels() {
327 let value = neighbor_space.prolong(
328 Interpolation::<ORDER>,
329 neighbor_node,
330 neighbor_system.channel(field),
331 );
332 block_system.channel_mut(field)[block_index] = value;
333 }
334 }
335 });
336 }
337
338 pub fn block_debug(&mut self, debug: &mut [i64]) {
340 assert!(debug.len() == self.num_nodes());
341
342 let debug = SharedSlice::new(debug);
343
344 self.block_compute(|mesh, _, block| {
345 let block_nodes = mesh.block_nodes(block);
346
347 for node in block_nodes {
348 unsafe {
349 *debug.get_mut(node) = block.0 as i64;
350 }
351 }
352 });
353 }
354
355 pub fn cell_debug(&mut self, debug: &mut [i64]) {
357 assert!(debug.len() == self.num_nodes());
358
359 let debug = SharedSlice::new(debug);
360
361 self.block_compute(|mesh, _, block| {
362 let block_nodes = mesh.block_nodes(block);
363 let block_space = mesh.block_space(block);
364 let block_size = mesh.blocks.size(block);
365 let cells = mesh.blocks.active_cells(block);
366
367 for (i, position) in IndexSpace::new(block_size).iter().enumerate() {
368 let cell = cells[i];
369 let origin: [_; N] = array::from_fn(|axis| (position[axis] * mesh.width) as isize);
370
371 for offset in IndexSpace::new([mesh.width + 1; N]).iter() {
372 let node = array::from_fn(|axis| origin[axis] + offset[axis] as isize);
373
374 let idx = block_nodes.start + block_space.index_from_node(node);
375
376 unsafe {
377 *debug.get_mut(idx) = cell.0 as i64;
378 }
379 }
380 }
381 });
382 }
383
384 pub fn interface_neighbor_debug(&mut self, extent: usize, debug: &mut [i64]) {
386 debug.fill(-1);
387
388 let debug = SharedSlice::new(debug);
389
390 self.interfaces
391 .iter()
392 .enumerate()
393 .for_each(|(iidx, interface)| {
394 let block_nodes = self.block_nodes(interface.block);
395 let block_space = self.block_space(interface.block);
396
397 for offset in self
398 .interfaces
399 .interface_nodes_active(NeighborId(iidx), extent)
400 {
401 let node = array::from_fn(|axis| interface.dest[axis] + offset[axis] as isize);
402 let index = block_space.index_from_node(node);
403
404 unsafe {
405 *debug.get_mut(block_nodes.start + index) = interface.neighbor.0 as i64;
406 }
407 }
408 });
409 }
410
411 pub fn interface_index_debug(&mut self, extent: usize, debug: &mut [i64]) {
413 debug.fill(-1);
414
415 let debug = SharedSlice::new(debug);
416
417 self.interfaces
418 .iter()
419 .enumerate()
420 .for_each(|(iidx, interface)| {
421 let block_nodes = self.block_nodes(interface.block);
422 let block_space = self.block_space(interface.block);
423
424 for offset in self
425 .interfaces
426 .interface_nodes_active(NeighborId(iidx), extent)
427 {
428 let node = array::from_fn(|axis| interface.dest[axis] + offset[axis] as isize);
429 let index = block_space.index_from_node(node);
430
431 unsafe {
432 *debug.get_mut(block_nodes.start + index) = iidx as i64;
433 }
434 }
435 });
436 }
437}