#[cfg(feature = "mpi-support")]
fn partition_vertices(nx: usize, ny: usize, size: usize) -> Vec<usize> {
let mut parts = vec![0; nx * ny];
let rows_per_rank = ny / size + if ny % size > 0 { 1 } else { 0 };
for y in 0..ny {
let rank = y / rows_per_rank;
for x in 0..nx {
let idx = y * nx + x;
parts[idx] = rank.min(size - 1);
}
}
parts
}
#[cfg(feature = "mpi-support")]
fn main() {
use mesh_sieve::algs::communicator::{Communicator, MpiComm};
use mesh_sieve::algs::rcm::distributed_rcm;
use mesh_sieve::topology::point::PointId;
use mesh_sieve::topology::sieve::{MeshSieve, Sieve};
let comm = MpiComm::new().expect("MPI initialization failed");
let rank = comm.rank();
let size = comm.size();
let nx = 4;
let ny = 4;
let mut sieve = MeshSieve::default();
for y in 0..ny {
for x in 0..nx {
let v = PointId::new((y * nx + x + 1) as u64).unwrap();
if x + 1 < nx {
let v_right = PointId::new((y * nx + (x + 1) + 1) as u64).unwrap();
sieve.add_arrow(v, v_right, ());
sieve.add_arrow(v_right, v, ());
}
if y + 1 < ny {
let v_down = PointId::new(((y + 1) * nx + x + 1) as u64).unwrap();
sieve.add_arrow(v, v_down, ());
sieve.add_arrow(v_down, v, ());
}
}
}
let parts = partition_vertices(nx, ny, size);
let local_vertices: Vec<_> = (0..nx * ny)
.filter(|&i| parts[i] == rank)
.map(|i| PointId::new((i + 1) as u64).unwrap())
.collect();
let mut local_sieve = MeshSieve::default();
for &v in &local_vertices {
for (tgt, _) in sieve.cone(v) {
if local_vertices.contains(&tgt) {
local_sieve.add_arrow(v, tgt, ());
}
}
}
println!("Rank {}: local vertices = {:?}", rank, local_vertices);
let local_edge_count: usize = local_vertices.iter().map(|&v| sieve.cone(v).count()).sum();
println!("Rank {}: local edges = {}", rank, local_edge_count);
let rcm_order = distributed_rcm(&local_sieve, &comm);
let mut rcm_sorted = rcm_order.clone();
rcm_sorted.sort_by_key(|pid| pid.get());
let mut expected = local_vertices.clone();
expected.sort_by_key(|pid| pid.get());
let valid = rcm_sorted == expected;
assert!(
valid,
"RCM order is not a valid permutation for rank {}",
rank
);
println!("Rank {}: RCM order {:?}", rank, rcm_order);
comm.barrier();
}
#[cfg(not(feature = "mpi-support"))]
fn main() {
eprintln!("This example requires the 'mpi-support' feature to run.");
}