use mesh_sieve::data::atlas::Atlas;
use mesh_sieve::data::refine::sieved_array::SievedArray;
use mesh_sieve::data::section::Section;
use mesh_sieve::data::storage::VecStorage;
use mesh_sieve::topology::arrow::Polarity;
use mesh_sieve::topology::point::PointId;
use mesh_sieve::topology::sieve::Sieve;
use mesh_sieve::overlap::overlap::*;
#[cfg(feature = "mpi-support")]
use mesh_sieve::partitioning::{
PartitionerConfig,
metrics::{edge_cut, replication_factor},
partition,
};
#[cfg(feature = "mpi-support")]
#[path = "support/test_graph_impl.rs"]
mod test_graph;
#[path = "support/tiny_mesh.rs"]
mod tiny_mesh;
#[cfg(feature = "rayon")]
fn check_parallel_refine_matches_serial(
atlas: &Atlas,
sec: &Section<f64, VecStorage<f64>>,
q0: PointId,
q1: PointId,
) {
use mesh_sieve::data::refine::sieved_array::SievedArray;
use mesh_sieve::topology::arrow::Polarity;
let mut src = SievedArray::<PointId, f64>::new(atlas.clone());
for (p, sl) in sec.iter() {
src.try_set(p, sl).unwrap();
}
let sifter = vec![
(q0, vec![(q0, Polarity::Forward)]),
(q1, vec![(q1, Polarity::Reverse)]),
];
let mut serial = SievedArray::<PointId, f64>::new(atlas.clone());
let mut parallel = SievedArray::<PointId, f64>::new(atlas.clone());
serial.try_refine_with_sifter(&src, &sifter).unwrap();
parallel
.try_refine_with_sifter_parallel(&src, &sifter)
.unwrap();
for &p in &[q0, q1] {
assert_eq!(serial.try_get(p).unwrap(), parallel.try_get(p).unwrap());
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let mesh = tiny_mesh::tiny_oriented_mesh();
let q0 = PointId::new(200).unwrap();
let q1 = PointId::new(201).unwrap();
let c0: Vec<_> = mesh.closure(std::iter::once(q0)).collect();
let s0: Vec<_> = mesh.star(std::iter::once(q0)).collect();
println!("[mesh] closure(Q0)={:?} star(Q0)={:?}", c0, s0);
assert!(!c0.is_empty() && !s0.is_empty());
let mut atlas = Atlas::default();
let off_q0 = atlas.try_insert(q0, 4)?; let off_q1 = atlas.try_insert(q1, 4)?;
assert_eq!(off_q0, 0);
assert_eq!(off_q1, 4);
let mut sec: Section<f64, VecStorage<f64>> = Section::new(atlas.clone());
sec.try_set(q0, &[1.0, 2.0, 3.0, 4.0])?;
sec.try_set(q1, &[10.0, 20.0, 30.0, 40.0])?;
let mut fine = SievedArray::<PointId, f64>::new(atlas.clone());
let mut coarse = SievedArray::<PointId, f64>::new(atlas.clone());
for (p, sl) in sec.iter() {
coarse.try_set(p, sl)?;
}
let sifter = vec![
(q0, vec![(q0, Polarity::Forward)]),
(q1, vec![(q1, Polarity::Reverse)]),
];
fine.try_refine_with_sifter(&coarse, &sifter)?;
let q1_src = sec.try_restrict(q1)?.to_vec();
let q1_fine = fine.try_get(q1)?.to_vec();
assert_eq!(q1_fine, q1_src.iter().rev().cloned().collect::<Vec<_>>());
#[cfg(feature = "rayon")]
check_parallel_refine_matches_serial(&atlas, &sec, q0, q1);
let mut ov = Overlap::default();
ov.add_link_structural_one(q0, 1);
ov.add_link_structural_one(q1, 0);
ensure_closure_of_support(&mut ov, &mesh);
ov.resolve_remote_point(q0, 1, q0)?;
#[cfg(any(
debug_assertions,
feature = "strict-invariants",
feature = "check-invariants"
))]
ov.validate_invariants().expect("overlap invariants");
let nbrs: Vec<_> = ov.neighbor_ranks().collect();
println!("[overlap] neighbor ranks = {:?}", nbrs);
assert!(nbrs.contains(&0) || nbrs.contains(&1));
let links_to_1: Vec<_> = ov.links_to(1).collect();
println!("[overlap] links to rank 1 = {:?}", links_to_1);
assert!(links_to_1.iter().any(|(p, rp)| *p == q0 && rp.is_some()));
#[cfg(feature = "mpi-support")]
{
let edges = tiny_mesh::tiny_dual_graph_edges();
let g = test_graph::AdjListGraph::from_undirected(2, &edges);
let cfg = PartitionerConfig {
n_parts: 2,
alpha: 0.75,
seed_factor: 4.0,
rng_seed: 1234,
max_iters: 20,
epsilon: 0.10,
enable_phase1: true,
enable_phase2: true,
enable_phase3: true,
};
let pm = match partition(&g, &cfg) {
Ok(pm) => pm,
Err(mesh_sieve::partitioning::PartitionerError::Unbalanced { .. }) => {
let cfg2 = PartitionerConfig {
enable_phase1: false,
..cfg
};
println!(
"[partition] Phase1 produced 1 cluster; retrying with enable_phase1=false"
);
partition(&g, &cfg2).expect("partition fallback runs")
}
Err(e) => panic!("partition runs: {:?}", e),
};
let cut = edge_cut(&g, &pm);
let rf_approx = replication_factor(&g, &pm);
println!("[partition] edge_cut={} RF≈{:.3}", cut, rf_approx);
assert!(cut <= 1);
assert!(rf_approx >= 1.0 && rf_approx <= 2.0);
#[cfg(feature = "exact-metrics")]
{
use mesh_sieve::partitioning::vertex_cut::build_vertex_cuts;
use std::collections::HashSet;
let (primary, replicas) = build_vertex_cuts(&g, &pm, 999).expect("vcuts");
let mut parts = vec![HashSet::new(), HashSet::new()];
for v in 0..2 {
parts[v].insert(primary[v]);
for &(_u, p) in &replicas[v] {
parts[v].insert(p);
}
}
let rf_exact = (parts[0].len() + parts[1].len()) as f64 / 2.0;
println!("[partition] RF_exact={:.3}", rf_exact);
assert!((rf_exact - rf_approx).abs() <= 1e-6 || rf_exact <= 2.0);
}
}
let p_bad = PointId::new(999).unwrap();
let mut bad = atlas.clone();
let err = bad.try_insert(p_bad, 0).unwrap_err();
println!("[neg] zero-length insert -> {:?}", err);
let mut sec2: Section<f64, VecStorage<f64>> = Section::new(atlas.clone());
let err = sec2.try_set(q0, &[1.0, 2.0, 3.0]).unwrap_err();
println!("[neg] slice-length mismatch -> {:?}", err);
#[cfg(any(feature = "strict-invariants", feature = "check-invariants"))]
{
use mesh_sieve::overlap::overlap::{OvlId, Remote};
let src = OvlId::Local(q0);
let dst = OvlId::Part(7);
let mut ov_bad = ov.clone();
Sieve::add_arrow(
&mut ov_bad,
src,
dst,
Remote {
rank: 5,
remote_point: None,
},
);
assert!(ov_bad.validate_invariants().is_err());
}
println!("OK: e2e showcase finished");
Ok(())
}