use core::ops::Range;
use super::coeffs::Coefficients;
use super::fields::Block;
use super::grid::Grid;
use crate::axis::Axis;
#[derive(Debug, Clone, Copy)]
pub struct SlabPartition<'a> {
pub(crate) grid: &'a Grid,
pub(crate) dt: f64,
pub(crate) starts: &'a [usize],
}
impl SlabPartition<'_> {
pub fn grid(&self) -> &Grid {
self.grid
}
pub fn dt(&self) -> f64 {
self.dt
}
pub fn slabs(&self) -> usize {
self.starts.len() - 1
}
pub fn planes(&self, s: usize) -> Range<usize> {
self.starts[s]..self.starts[s + 1]
}
}
#[derive(Debug, Clone, Copy)]
pub struct SlabContext<'a> {
pub slab: usize,
pub step: u64,
pub dt: f64,
pub coefficients: &'a Coefficients,
}
#[derive(Debug)]
pub struct SlabMut<'a> {
pub(crate) n: [usize; 3],
pub(crate) planes: Range<usize>,
pub(crate) block: &'a mut Block,
}
impl SlabMut<'_> {
pub fn nodes(&self) -> [usize; 3] {
self.n
}
pub fn planes(&self) -> Range<usize> {
self.planes.clone()
}
fn offset(&self, i: usize) -> usize {
assert!(
self.planes.contains(&i),
"x-plane {i} is not in slab {:?}",
self.planes
);
(i - self.planes.start) * self.n[1] * self.n[2]
}
pub fn plane(&self, axis: Axis, i: usize) -> &[f32] {
let o = self.offset(i);
&self.block[axis.index()][o..o + self.n[1] * self.n[2]]
}
pub fn plane_mut(&mut self, axis: Axis, i: usize) -> &mut [f32] {
let o = self.offset(i);
let p = self.n[1] * self.n[2];
&mut self.block[axis.index()][o..o + p]
}
}
#[derive(Debug)]
pub struct SlabRef<'a> {
pub(crate) n: [usize; 3],
pub(crate) planes: Range<usize>,
pub(crate) block: &'a Block,
pub(crate) neighbour: Option<(usize, &'a Block, usize)>,
}
impl SlabRef<'_> {
pub fn nodes(&self) -> [usize; 3] {
self.n
}
pub fn planes(&self) -> Range<usize> {
self.planes.clone()
}
pub fn try_plane(&self, axis: Axis, i: usize) -> Option<&[f32]> {
let p = self.n[1] * self.n[2];
let (b, l) = if self.planes.contains(&i) {
(self.block, i - self.planes.start)
} else {
match self.neighbour {
Some((g, b, l)) if g == i => (b, l),
_ => return None,
}
};
Some(&b[axis.index()][l * p..(l + 1) * p])
}
pub fn plane(&self, axis: Axis, i: usize) -> &[f32] {
self.try_plane(axis, i)
.unwrap_or_else(|| panic!("x-plane {i} is not readable from slab {:?}", self.planes))
}
}
pub trait SlabHooks: Send + Sync + 'static {
fn post_h_slab(&self, _i: &mut SlabMut<'_>, _u: &SlabRef<'_>, _ctx: &SlabContext<'_>) {}
fn post_e_slab(&self, _u: &mut SlabMut<'_>, _i: &SlabRef<'_>, _ctx: &SlabContext<'_>) {}
}