use crate::{const_generic::storage::{GridPoint, SparseGridData}, errors::SGError};
pub trait Generator<const D: usize> : Default
{
#[allow(non_snake_case)]
fn regular(&self, storage: &mut SparseGridData<D>, levels: [usize; D], T :Option<f64>) -> Result<(), SGError>;
fn full(&self, storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError>;
fn full_with_boundaries(&self, storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError>;
#[allow(non_snake_case)]
fn regular_with_boundaries(&self, storage: &mut SparseGridData<D>, levels: [usize; D], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError>;
}
#[allow(non_snake_case)]
fn regular_generator_iterative<const D: usize>(storage: &mut SparseGridData<D>, levels: [usize; D], T :Option<f64>) -> Result<(), SGError>
{
let mut point = GridPoint::new([1; D], [1;D], false);
let t = T.unwrap_or(0.0); let n = levels[0] as u32;
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point);
}
}
#[allow(clippy::needless_range_loop)]
for d in 1..D
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut first = true;
let mut point: GridPoint<D> = storage[g];
let level_sum = point.level_sum() - 1;
let level_max = point.level_max();
let mut l = 1;
let n = levels[d] as u32;
while (l + level_sum) as f64 - (t * l.max(level_max) as f64) <= (n + D as u32 - 1) as f64 - (t * n as f64) && l.max(level_max) as u32 <= n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = (l + level_sum) as u32 == n + D as u32 - 1;
point.level[d] = l;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first
{
storage.insert_point(point);
}
else
{
storage.update(point, g);
first = false;
}
}
l += 1;
}
}
}
Ok(())
}
#[allow(non_snake_case)]
pub fn regular<const D: usize>(storage: &mut SparseGridData<D>, levels: [usize; D], T :Option<f64>) -> Result<(), SGError>
{
regular_generator_iterative(storage, levels, T)
}
fn full_iterative<const D: usize>(storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError>
{
let mut point = GridPoint::new([1; D], [1;D], false);
let n = level as u32;
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point);
}
}
for d in 1..D
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut first = true;
let mut point: GridPoint<D> = storage[g];
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = point.level_sum() as u32 == n * D as u32;
point.level[d] = l as u8;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first
{
storage.insert_point(point);
}
else
{
storage.update(point, g);
first = false;
}
}
}
}
}
Ok(())
}
pub fn full<const D: usize>(storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError> {
full_iterative(storage, level)
}
pub fn full_with_boundaries<const D: usize>(storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError> {
full_with_boundaries_iter(storage, level)?;
storage.has_boundary = true;
Ok(())
}
#[allow(non_snake_case)]
pub fn regular_with_boundaries<const D: usize>(storage: &mut SparseGridData<D>, levels: [usize; D], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError> {
let boundary_level = boundary_level.unwrap_or(1);
if boundary_level > 0
{
regular_with_boundaries_iter(storage, levels, Some(boundary_level), T)?;
storage.has_boundary = true;
Ok(())
}
else
{
Err(SGError::NotImplemented)
}
}
#[allow(non_snake_case)]
fn regular_with_boundaries_iter<const D:usize>(storage: &mut SparseGridData<D>, levels: [usize; D], boundary_level: Option<usize>, T :Option<f64>) -> Result<(), SGError>
{
let boundary_level = boundary_level.unwrap_or(1) as u32;
let mut point = GridPoint::new([1; D], [1;D], false);
let t = T.unwrap_or(0.0); let n = levels[0] as u32;
point.level[0] = 0;
point.index[0] = 0;
storage.insert_point(point);
point.index[0] = 1;
storage.insert_point(point);
for l in 1..=n
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point);
}
}
for d in 1..D as u32
{
let ngrids = storage.len();
let cur_dim = d+1;
for g in 0..ngrids
{
let mut point: GridPoint<D> = storage[g];
let mut level_sum = 0;
let mut num_zero_levels = 0;
for j in 0..d as usize
{
let lvl = point.level[j];
if lvl == 0
{
num_zero_levels += 1;
}
level_sum += lvl;
}
let mut first_point = true;
if (level_sum as u32 + boundary_level + num_zero_levels < n + cur_dim) || (num_zero_levels == cur_dim - 1)
{
point.level[d as usize] = 0;
point.index[d as usize] = 0;
point.set_is_leaf(false);
storage.update(point, g);
point.index[d as usize] = 1;
storage.insert_point(point);
first_point = false;
}
let mut upper_bound = if num_zero_levels > 0
{
if n + cur_dim < boundary_level + num_zero_levels
{
continue;
} else {
(n + cur_dim - num_zero_levels - boundary_level) as f64
}
}
else
{
(n + cur_dim - 1) as f64
};
upper_bound -= t * n as f64;
let level_max = point.level_max();
let mut l = 1;
let d = d as usize;
let n = levels[d];
while (l + level_sum) as f64 - (t * l.max(level_max) as f64) <= upper_bound && l.max(level_max) <= n as u8
{
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = if l as u32 +level_sum as u32 == n as u32 + D as u32 - 1 { num_zero_levels == 0 } else { false};
point.level[d] = l;
point.index[d] = i;
point.set_is_leaf(is_leaf);
if !first_point
{
storage.insert_point(point);
}
else
{
storage.update(point, g);
first_point = false;
}
}
l += 1;
}
}
}
Ok(())
}
fn full_with_boundaries_iter<const D:usize>(storage: &mut SparseGridData<D>, level: usize) -> Result<(), SGError>
{
let mut point = GridPoint::new([1; D], [1;D], false);
let n = level as u32;
for l in 1..=n
{
if l == 1
{
point.level[0] = 0;
point.index[0] = 0;
point.set_is_leaf(false);
storage.insert_point(point);
point.index[0] = 1;
storage.insert_point(point);
}
for i in (1..(1 << l)).step_by(2)
{
let is_leaf = l == n;
point.level[0] = l as u8;
point.index[0] = i;
point.set_is_leaf(is_leaf);
storage.insert_point(point);
}
}
for d in 1..D as u32
{
let ngrids = storage.len();
for g in 0..ngrids
{
let mut point: GridPoint<D> = storage[g];
for l in 1..=n
{
if l == 1
{
point.level[d as usize] = 0;
point.index[d as usize] = 0;
point.set_is_leaf(false);
storage.update(point, g);
point.index[d as usize] = 1;
storage.insert_point(point);
}
point.level[d as usize] = l as u8;
for i in (1..(1 <<l)).step_by(2)
{
point.index[d as usize] = i;
point.set_is_leaf(point.level_sum() as u32 == n * D as u32);
storage.insert_point(point);
}
}
}
}
Ok(())
}
#[test]
fn test_regular()
{
let mut storage = SparseGridData::<2>::default();
regular(&mut storage, [3,3], Some(0.0)).expect("Could not generate grid.");
assert_eq!(storage.len(), 17);
}
#[test]
fn test_truncated_boundaries_1d()
{
let mut storage = SparseGridData::<1>::default();
regular_with_boundaries(&mut storage, [2], Some(1), None).expect("Could not generate grid.");
assert_eq!(storage.len(), 5);
}
#[test]
fn test_truncated_boundaries_2d()
{
let mut storage = SparseGridData::<2>::default();
regular_with_boundaries(&mut storage, [2,2], Some(1), None).expect("Could not generate grid.");
assert_eq!(storage.len(), 21);
let mut storage2 = SparseGridData::<2>::default();
regular_with_boundaries(&mut storage2, [3,3], Some(1), None).expect("Could not generate grid.");
assert_eq!(storage2.len(), 49);
assert!(storage2.contains(&GridPoint::new([1,1], [1,1], false)));
assert!(storage2.contains(&GridPoint::new([1,2], [1,1], false)));
assert!(storage2.contains(&GridPoint::new([2,2], [3,1], false)));
assert!(!storage2.contains(&GridPoint::new([3,2], [5,1], false)));
assert!(storage2.contains(&GridPoint::new([3,1], [5,1], false)));
assert!(storage2.contains(&GridPoint::new([3,0], [5,0], false)));
assert!(storage2.contains(&GridPoint::new([0,0], [0,0], false)));
}