use crate::const_generic::{iterators::grid_iterator::{GridIteratorT, HashMapGridIterator}, storage::SparseGridData};
use super::refinement::RefinementFunctor;
fn add_required_boundary_closure<const D: usize>(iterator: &mut HashMapGridIterator<D>, storage: &SparseGridData<D>, keep: &mut [bool])
{
let mut changed = true;
while changed
{
changed = false;
for seq in 0..storage.len()
{
if !keep[seq]
{
continue;
}
let point = storage.nodes()[seq];
for dim in 0..D
{
iterator.set_index(point);
if iterator.reset_to_left_level_zero(dim)
{
let boundary_seq = iterator.index().unwrap();
if !keep[boundary_seq]
{
keep[boundary_seq] = true;
changed = true;
}
}
iterator.set_index(point);
if iterator.reset_to_right_level_zero(dim)
{
let boundary_seq = iterator.index().unwrap();
if !keep[boundary_seq]
{
keep[boundary_seq] = true;
changed = true;
}
}
}
}
}
}
fn keep_mask_to_indices(keep: &[bool]) -> Vec<usize>
{
let mut kept_points = Vec::with_capacity(keep.iter().filter(|&&keep| keep).count());
for (seq, &is_kept) in keep.iter().enumerate()
{
if is_kept
{
kept_points.push(seq);
}
}
kept_points
}
pub(crate) fn coarsen<const D: usize, const DIM_OUT: usize>( storage: &mut SparseGridData<D>, functor: &dyn RefinementFunctor<D, DIM_OUT>, alpha: &[[f64; DIM_OUT]], values: &[[f64; DIM_OUT]], threshold: f64, remove_boundary: bool) -> Vec<usize>
{
let mut iterator = HashMapGridIterator::new(storage);
let mut keep = vec![false; storage.len()];
iterator.reset_to_level_zero();
let zero_index = iterator.index().unwrap();
let values = functor.eval(storage.points(), alpha, values);
for (seq, (point, r)) in storage.nodes().iter().zip(values.iter()).enumerate()
{
if point.is_inner_point()
{
if point.is_leaf() && seq != zero_index
{
if *r >= threshold
{
keep[seq] = true;
}
}
else
{
keep[seq] = true;
}
}
}
if remove_boundary
{
for (seq, (point, r)) in storage.nodes().iter().zip(values.iter()).enumerate()
{
if !point.is_inner_point()
{
if seq == zero_index || !point.is_leaf() || *r >= threshold
{
keep[seq] = true;
}
}
}
add_required_boundary_closure(&mut iterator, storage, &mut keep);
}
else
{
for (seq, point) in storage.nodes().iter().enumerate()
{
if !point.is_inner_point()
{
keep[seq] = true;
}
}
}
let kept_points = keep_mask_to_indices(&keep);
storage.remove(&kept_points);
kept_points
}