Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions applications/incremental_delaunay/internals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ pub fn delaunay_box_3d<T: CoordsFloat>(
T::from(ly).unwrap(),
T::from(lz).unwrap(),
])
// .enable_vertex_id_cache(true)
.split_cells(true)
.build()
.unwrap()
Expand Down
3 changes: 2 additions & 1 deletion honeycomb-core/src/cmap/builder/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ pub fn build_2d_from_cmap_file<T: CoordsFloat>(
#[allow(clippy::too_many_lines)]
pub fn build_3d_from_cmap_file<T: CoordsFloat>(
f: CMapFile,
enable_vid_cache: bool,
manager: AttrStorageManager, // FIXME: find a cleaner solution to populate the manager
) -> Result<CMap3<T>, BuilderError> {
if f.meta.1 != 3 {
Expand All @@ -214,7 +215,7 @@ pub fn build_3d_from_cmap_file<T: CoordsFloat>(
"mismatch between requested dimension and header",
));
}
let map = CMap3::new_with_undefined_attributes(f.meta.2, manager);
let map = CMap3::new_with_undefined_attributes(f.meta.2, enable_vid_cache, manager);

// putting it in a scope to drop the data
let betas = f.betas.lines().collect::<Vec<_>>();
Expand Down
22 changes: 21 additions & 1 deletion honeycomb-core/src/cmap/builder/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub enum BuilderError {
pub struct CMapBuilder<const D: usize> {
builder_kind: BuilderType,
attributes: AttrStorageManager,
enable_vid_cache: bool,
}

enum BuilderType {
Expand Down Expand Up @@ -101,9 +102,12 @@ impl<T: CoordsFloat> Builder<T> for CMapBuilder<3> {

fn build(self) -> Result<Self::MapType, BuilderError> {
match self.builder_kind {
BuilderType::CMap(cfile) => super::io::build_3d_from_cmap_file(cfile, self.attributes),
BuilderType::CMap(cfile) => {
super::io::build_3d_from_cmap_file(cfile, self.enable_vid_cache, self.attributes)
}
BuilderType::FreeDarts(n_darts) => Ok(CMap3::new_with_undefined_attributes(
n_darts,
self.enable_vid_cache,
self.attributes,
)),
BuilderType::Vtk(_vfile) => unimplemented!(),
Expand All @@ -119,6 +123,7 @@ impl<const D: usize> CMapBuilder<D> {
Self {
builder_kind: BuilderType::FreeDarts(n_darts),
attributes: other.attributes,
enable_vid_cache: false,
}
}

Expand All @@ -128,6 +133,7 @@ impl<const D: usize> CMapBuilder<D> {
Self {
builder_kind: BuilderType::FreeDarts(n_darts),
attributes: AttrStorageManager::default(),
enable_vid_cache: false,
}
}

Expand All @@ -147,6 +153,7 @@ impl<const D: usize> CMapBuilder<D> {
Self {
builder_kind: BuilderType::CMap(cmap_file),
attributes: AttrStorageManager::default(),
enable_vid_cache: false,
}
}

Expand All @@ -163,6 +170,7 @@ impl<const D: usize> CMapBuilder<D> {
Self {
builder_kind: BuilderType::Vtk(vtk_file),
attributes: AttrStorageManager::default(),
enable_vid_cache: false,
}
}

Expand All @@ -184,6 +192,18 @@ impl<const D: usize> CMapBuilder<D> {
self
}

/// Enable usage of an internal vertex ID cache.
///
/// By default, vertex IDs are recomputed at each call of the `vertex_id(_tx)` methods. By
/// enabling this cache, vertex IDs associated to darts are instead stored in a dedicated
/// collection, and updated on (un)sews. This can be useful for algorithm which frequently
/// use this data.
#[must_use = "unused builder object"]
pub fn enable_vertex_id_cache(mut self, enable: bool) -> Self {
self.enable_vid_cache = enable;
self
}

#[allow(clippy::missing_errors_doc)]
/// Consumes the builder and produce a combinatorial map object.
///
Expand Down
58 changes: 31 additions & 27 deletions honeycomb-core/src/cmap/dim3/basic_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,35 +181,39 @@ impl<T: CoordsFloat> CMap3<T> {
t: &mut Transaction,
dart_id: DartIdType,
) -> Result<VertexIdType, StmError> {
AUXILIARIES.with(|cell| {
let (pending, marked) = &mut *cell.borrow_mut();
// clear from previous computations
pending.clear();
marked.clear();
// initialize
pending.push_front(dart_id);
marked.insert(NULL_DART_ID); // we don't want to include the null dart in the orbit

let mut min = dart_id;

while let Some(d) = pending.pop_front() {
if marked.insert(d) {
min = min.min(d);
let (b0, b2, b3) = (
self.beta_tx::<0>(t, d)?, // ?
self.beta_tx::<2>(t, d)?,
self.beta_tx::<3>(t, d)?,
);
pending.push_back(self.beta_tx::<1>(t, b3)?);
pending.push_back(self.beta_tx::<3>(t, b2)?);
pending.push_back(self.beta_tx::<1>(t, b2)?);
pending.push_back(self.beta_tx::<3>(t, b0)?); // ?
pending.push_back(self.beta_tx::<2>(t, b0)?); // ?
if let Some(ref vids) = self.vid_cache {
vids[dart_id as usize].read(t)
} else {
AUXILIARIES.with(|cell| {
let (pending, marked) = &mut *cell.borrow_mut();
// clear from previous computations
pending.clear();
marked.clear();
// initialize
pending.push_front(dart_id);
marked.insert(NULL_DART_ID); // we don't want to include the null dart in the orbit

let mut min = dart_id;

while let Some(d) = pending.pop_front() {
if marked.insert(d) {
min = min.min(d);
let (b0, b2, b3) = (
self.beta_tx::<0>(t, d)?,
self.beta_tx::<2>(t, d)?,
self.beta_tx::<3>(t, d)?,
);
pending.push_back(self.beta_tx::<1>(t, b3)?);
pending.push_back(self.beta_tx::<3>(t, b2)?);
pending.push_back(self.beta_tx::<1>(t, b2)?);
pending.push_back(self.beta_tx::<3>(t, b0)?);
pending.push_back(self.beta_tx::<2>(t, b0)?);
}
}
}

Ok(min)
})
Ok(min)
})
}
}

/// Compute the ID of the edge a given dart is part of.
Expand Down
52 changes: 51 additions & 1 deletion honeycomb-core/src/cmap/dim3/links/one.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! 1D link implementations

use crate::cmap::{CMap3, DartIdType, LinkError, NULL_DART_ID};
use crate::cmap::{CMap3, DartIdType, LinkError, NULL_DART_ID, OrbitPolicy};
use crate::geometry::CoordsFloat;
use crate::stm::{Transaction, TransactionClosureResult, abort, atomically_with_err};

Expand All @@ -18,6 +18,24 @@ impl<T: CoordsFloat> CMap3<T> {
if b3_ld != NULL_DART_ID && b3_rd != NULL_DART_ID {
self.betas.one_link_core(t, b3_rd, b3_ld)?;
}
if let Some(ref vids) = self.vid_cache {
let b2_ld = self.beta_tx::<2>(t, ld)?;
let ll = b2_ld.max(b3_ld);
if ll != NULL_DART_ID {
let lvid = vids[ll as usize].read(t)?;
let rvid = vids[rd as usize].read(t)?;
if lvid != rvid {
let new_vid = lvid.min(rvid);
let mut darts = Vec::with_capacity(16);
for d in self.orbit_tx(t, OrbitPolicy::Vertex, ll) {
darts.push(d?);
}
for d in darts {
vids[d as usize].write(t, new_vid)?;
}
}
}
}
Ok(())
}

Expand Down Expand Up @@ -48,6 +66,38 @@ impl<T: CoordsFloat> CMap3<T> {
}
self.betas.one_unlink_core(t, b3_rd)?;
}
if let Some(ref vids) = self.vid_cache {
let b2_ld = self.beta_tx::<2>(t, ld)?;
let ll = b2_ld.max(b3_ld);
if ll != NULL_DART_ID {
let mut l_orbit = Vec::with_capacity(16);
let mut lvid = ll;
for d in self.orbit_tx(t, OrbitPolicy::Vertex, ll) {
let d = d?;
l_orbit.push(d);
if d < lvid {
lvid = d;
}
}
let mut r_orbit = Vec::with_capacity(16);
let mut rvid = rd;
for d in self.orbit_tx(t, OrbitPolicy::Vertex, rd) {
let d = d?;
r_orbit.push(d);
if d < rvid {
rvid = d;
}
}
if lvid != rvid {
for d in l_orbit {
vids[d as usize].write(t, lvid)?;
}
for d in r_orbit {
vids[d as usize].write(t, rvid)?;
}
}
}
}
Ok(())
}

Expand Down
Loading
Loading