use crate::dynamic::{iterators::dynamic_grid_iterator::DynamicHashMapGridIterator, storage::SparseGridData};
use super::refinement::RefinementFunctor;
fn add_required_boundary_closure(iterator: &mut DynamicHashMapGridIterator, storage: &SparseGridData, keep: &mut [bool])
{
use crate::dynamic::iterators::dynamic_grid_iterator::GridIteratorT;
let mut changed = true;
while changed
{
changed = false;
for seq in 0..storage.len()
{
if !keep[seq]
{
continue;
}
let point = storage.point(seq);
for dim in 0..storage.num_inputs()
{
iterator.set_index(point.clone());
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.clone());
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(|&&is_kept| is_kept).count());
for (seq, &is_kept) in keep.iter().enumerate()
{
if is_kept
{
kept_points.push(seq);
}
}
kept_points
}
pub(crate) fn coarsen(storage: &mut SparseGridData, functor: &dyn RefinementFunctor, alpha: &[f64], values: &[f64], threshold: f64, remove_boundary: bool) -> Vec<usize>
{
let mut iterator = DynamicHashMapGridIterator::new(storage);
let mut keep = vec![false; storage.len()];
let zero_index = storage.adjacency_data.zero_index;
let values = functor.eval(storage.points(), alpha, values);
for (seq, r) in values.iter().enumerate()
{
let is_leaf = storage.is_leaf(seq);
let is_inner = storage.is_inner_point(seq);
if is_inner
{
if is_leaf && seq != zero_index
{
if *r >= threshold
{
keep[seq] = true;
}
}
else
{
keep[seq] = true;
}
}
}
if remove_boundary
{
for (seq, r) in values.iter().enumerate()
{
if !storage.is_inner_point(seq)
{
let is_leaf = storage.is_leaf(seq);
if seq == zero_index || !is_leaf || *r >= threshold
{
keep[seq] = true;
}
}
}
add_required_boundary_closure(&mut iterator, storage, &mut keep);
}
else
{
#[allow(clippy::needless_range_loop)]
for seq in 0..storage.len()
{
if !storage.is_inner_point(seq)
{
keep[seq] = true;
}
}
}
let kept_points = keep_mask_to_indices(&keep);
storage.remove(&kept_points);
kept_points
}