honeycomb_benches/
grid_gen.rs

1use std::time::{Duration, Instant};
2
3use honeycomb::{
4    core::stm::atomically_with_err,
5    prelude::{CMap2, CMapBuilder, CoordsFloat, DartIdType, GridDescriptor, Orbit2, OrbitPolicy},
6};
7use rand::{
8    distr::{Bernoulli, Distribution},
9    rngs::SmallRng,
10    SeedableRng,
11};
12use rayon::prelude::*;
13
14use crate::cli::{Generate2dGridArgs, Split};
15
16pub fn bench_generate_2d_grid<T: CoordsFloat>(args: Generate2dGridArgs) -> CMap2<T> {
17    let descriptor = GridDescriptor::default()
18        .n_cells_x(args.nx.get())
19        .n_cells_y(args.ny.get())
20        .len_per_cell_x(T::from(args.lx).unwrap())
21        .len_per_cell_y(T::from(args.ly).unwrap())
22        .split_quads(args.split.is_some_and(|s| s == Split::Uniform));
23
24    let mut map = CMapBuilder::from(descriptor).build().unwrap();
25
26    if args.split.is_some_and(|s| s == Split::Random) {
27        // fixed probability and seed value from  the original binary
28        // this can be made into a CL arg if necessary
29        let _ = split_faces_randomly(&mut map, 0.6, 9_817_498_146_784);
30    }
31
32    map
33}
34
35fn split_faces_randomly<T: CoordsFloat>(
36    map: &mut CMap2<T>,
37    p_bernoulli: f64,
38    seed: u64,
39) -> (Duration, Duration) {
40    // sample
41    let mut instant = Instant::now();
42    let faces = map.iter_faces().collect::<Vec<_>>();
43    let n_diag = faces.len();
44    let rng = SmallRng::seed_from_u64(seed);
45    let dist = Bernoulli::new(p_bernoulli).unwrap();
46    let splits: Vec<bool> = dist.sample_iter(rng).take(n_diag).collect();
47    let sample_time = instant.elapsed();
48
49    // build diags
50    instant = Instant::now();
51    let nd = map.add_free_darts(n_diag * 2);
52    let nd_range = (nd..nd + (n_diag * 2) as DartIdType).collect::<Vec<_>>();
53    faces
54        .into_iter()
55        .zip(nd_range.chunks(2))
56        .zip(splits)
57        .par_bridge()
58        .for_each(|((df, sl), split)| {
59            let square = df as DartIdType;
60            assert_eq!(Orbit2::new(map, OrbitPolicy::FaceLinear, df).count(), 4);
61            let (ddown, dright, dup, dleft) = (square, square + 1, square + 2, square + 3);
62
63            let &[dsplit1, dsplit2] = sl else {
64                unreachable!()
65            };
66            let (dbefore1, dbefore2, dafter1, dafter2) = if split {
67                (ddown, dup, dleft, dright)
68            } else {
69                (dright, dleft, ddown, dup)
70            };
71            let _ = map.force_link::<2>(dsplit1, dsplit2);
72
73            while atomically_with_err(|trans| {
74                map.unsew::<1>(trans, dbefore1)?;
75                map.unsew::<1>(trans, dbefore2)?;
76                map.sew::<1>(trans, dsplit1, dafter1)?;
77                map.sew::<1>(trans, dsplit2, dafter2)?;
78
79                map.sew::<1>(trans, dbefore1, dsplit1)?;
80                map.sew::<1>(trans, dbefore2, dsplit2)?;
81                Ok(())
82            })
83            .is_err()
84            {}
85        });
86    (sample_time, instant.elapsed())
87}