use crate::mesh_error::MeshSieveError;
use crate::topology::arrow::Polarity;
use crate::topology::point::PointId;
use crate::topology::sieve::{InMemorySieve, Sieve};
use std::collections::HashSet;
pub type CoarseningMap = Vec<(PointId, Vec<(PointId, Polarity)>)>;
#[derive(Clone, Debug)]
pub struct CoarsenEntity {
pub coarse_point: PointId,
pub fine_points: Vec<(PointId, Polarity)>,
pub cone: Vec<PointId>,
}
#[derive(Clone, Debug)]
pub struct CoarsenedTopology {
pub sieve: InMemorySieve<PointId, ()>,
pub transfer_map: CoarseningMap,
}
pub fn coarsen_topology(
fine: &impl Sieve<Point = PointId>,
entities: &[CoarsenEntity],
) -> Result<CoarsenedTopology, MeshSieveError> {
let fine_points: HashSet<_> = fine.points().collect();
let mut coarse = InMemorySieve::<PointId, ()>::default();
let mut transfer_map = Vec::with_capacity(entities.len());
for entity in entities {
for (fine_point, _) in &entity.fine_points {
if !fine_points.contains(fine_point) {
return Err(MeshSieveError::UnknownPoint(format!("{fine_point:?}")));
}
}
for cone_point in &entity.cone {
if !fine_points.contains(cone_point) {
return Err(MeshSieveError::UnknownPoint(format!("{cone_point:?}")));
}
coarse.add_arrow(entity.coarse_point, *cone_point, ());
}
transfer_map.push((entity.coarse_point, entity.fine_points.clone()));
}
Ok(CoarsenedTopology {
sieve: coarse,
transfer_map,
})
}