Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <h2>Related works</h2>
<ul>
<li><a href="https://hal.science/hal-05121848v1">COMPAS 2025 short paper</a></li>
<li><a href="https://scientificcomputing.rs/2025/talks/muron.html">Scientific Computing in Rust 2025 talk</a></li>
<li><a href="https://drive.google.com/file/d/1D_SLFSMMlBc2ycZURztTXnwX6jN0A8r8/view">International Meshing Roundtable 2026 paper</a> and slides (published soon)</li>
<li><a href="https://epubs.siam.org/doi/10.1137/1.9781611979138.8">International Meshing Roundtable 2026 paper</a> and slides (published soon)</li>

</ul>

Expand Down
4 changes: 2 additions & 2 deletions user-guide/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [Element insertion and deletion](./definitions/ops.md)
- [Sewing operation](./definitions/sews.md)
- [Transactional memory](./definitions/stm.md)
- [Resources]()
- [Resources](./definitions/resources.md)

# User guide

Expand All @@ -26,7 +26,7 @@
- [Contributing](./dev-guide/contributing.md)
- [Project structure](./dev-guide/project-structure.md)
- [Library](./dev-guide/library.md)
- [Applications]()
- [Applications](./dev-guide/apps.md)

# Code examples

Expand Down
34 changes: 34 additions & 0 deletions user-guide/src/definitions/resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Resources

---

This page groups a few references mentioned in this book, as well as others which help understand
all mechanism leveraged in the framework.

## Rust

- The Rust Programming Language [book](https://doc.rust-lang.org/book/).
- Rust by Example [book](https://doc.rust-lang.org/rust-by-example/)
- Rust's standard library [documentation](https://doc.rust-lang.org/stable/std/)

## Combinatorial Maps

- G. Damiand and P. Lienhardt, _Combinatorial Maps: Efficient Data Structures for Computer Graphics
and Image Processing_, A K Peters/CRC Press, Sept. 2014.
- G. Damiand and M. Teillaud, _A Generic Implementation of dD Combinatorial Maps in CGAL_, Procedia
Engineering, 82 (2014), pp. 46–58.
- P. Kraemer, L. Untereiner, T. Jund, S. Thery, and D. Cazier, _CGoGN: N-dimensional Meshes with
Combinatorial Maps_, in Proceedings of the 22nd International Meshing Roundtable, J. Sarrate and
M. Staten, eds., Springer International Publishing, Cham, Oct. 2013, pp. 485–503.

## Transactional Memory

- Dedicated STM chapter of _Real World Haskell_ for
a quick intuitive introduction
- _Software Transactional Memory_, Shavit et al., 1997
- _On the correctness of transactional memory_, Guerraoui et al., 2008

## Algorithms

References are given on a case by case basis when it comes to algorithms. Some were loosely adapted
from references while others were direct re-implementations.
59 changes: 33 additions & 26 deletions user-guide/src/definitions/stm.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
# Transactional memory

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

Meshing operations demand guarantees for coordinated access across sets of variables. They may also
be composed of multiple steps that should not be interrupted, or where intermediate mesh state may
be invalid.

<figure style="text-align:center">
<img src="../images/cutedge-steps-with-ops.svg" alt="EdgeCutSteps" width=70%/>
<figcaption><i>Edge cut operation with detailed steps.</i></figcaption>
</figure>

For example, an edge cut in a triangular mesh is defined by the insertion of a vertex on
an existing edge, before the creation of two new edges that cut across the original adjacent
triangles. After the first vertex insertion, and before both edges creation, the mesh actually
contains quadrangular cells. This is a state that should not be visible to other threads, nor should
it be a final state.

## Needs

In order to guarantee validity, we must ensure that these intermediate, incorrect states aren’t
used by another thread to compute an erroneous result, i.e., that all changes made in a thread
appear at once to others. To obtain our final system, we worked incrementally on a synchronization
policy choice.

Rust's ownership semantics require us to add synchronization mechanism to our structure if we want
to use it in concurrent contexts. Using primitives such as atomics and mutexes would be enough to
get programs to compile, but it would respectively yield an incorrect or impractical implementation:

- Atomics give guarantees on instructions interleaving for a single given variable, they do not give
any guarantees for instructions affecting different atomic variables.
- Mutexes (and similar locks, e.g. RWLocks) can be used to create guarantees when accessing multiple
variable: for example, we can write an operation that does not progress until all of the used data
is locked. However, locks are error-prone, have very poor composability.
- Atomics give guarantees on instructions interleaving for a single given variable, these guarantees
cannot be extended to a set of accesses across different variables.
- Mutexes (and similar locks, e.g. RWLocks) can be used to implement greater synchronization
coordination: for example, we can write an operation that does not progress until all of the used
data is locked. However, locks are error-prone, have very poor composability. Issues that come
with those grow along the number of locks used.

The nature of meshing operations makes both mechanisms very unpractical. They are complex, access
many variables, and are often comprised of multiple steps. For example, the following operation is
executed on all affected attributes of a sew:

<figure style="text-align:center">
<img src="../images/attribute_merge.svg" alt="Merge Operation" />
<figcaption><i>Attribute merging operation. This occurs at each sew operation.</i></figcaption>
</figure>

Because the map can go through invalid intermediate states during a single operation, we need to
ensure another thread will not use one of these as the starting point for another operation. This
rules out fine-grained atomics.

The sew operation is the main method used to create new connectivities in the map. This means that
most high-level meshing operations will call this method multiple times. If these meshing operations
require locking all of the variables to ensure correct execution, the locks must be returned or
exposed to the user so that he can unlock them at the right time. Manual lock management is
error-prone, and becomes impossible in practice for complex meshing operations.
We detail how these usual mechanisms fail to provide the guarantees we need in one of
[our paper](https://epubs.siam.org/doi/10.1137/1.9781611979138.8).


## Software Transactional Memory
Expand All @@ -43,6 +45,11 @@ We choose to use Software Transactional Memory (STM) to handle high-level synchr
the structure. Unlike locks, STM has great composability and allows users of the crate to easily
define pseudo-atomic segments in their own algorithms.

<figure style="text-align:center">
<img src="../images/cutedge-resolution.svg" alt="EdgeCutSTM" width=100%/>
<figcaption><i>Edge cut operation with detailed steps.</i></figcaption>
</figure>

Exposing an API that allows users to handle synchronization also means that the implementation
isn't bound to a given parallelization framework. Instead of relying on predefinite parallel
routines (e.g. a provided `parallel_for` on given cells), the structure can be used to implement
Expand Down
92 changes: 92 additions & 0 deletions user-guide/src/dev-guide/apps.md
Original file line number Diff line number Diff line change
@@ -1 +1,93 @@
# Applications

---

The `applications` crate contains multiple binaries which serve as benchmarks and examples for the
library. The following targets are defined:

| Algorithm | Target binary | Dimension |
| ------------------------------------ | ---------------------- | --------- |
| Delaunay triangulation | `incremental-delaunay` | 3D |
| Edge cut | `cut-edges` | 2D |
| Overlay grid (intersection-based) | `grisubal` | 2D |
| Overlay grid (refinement-based) | `overlay-grid` | 2D |
| Parameterized grid generation | `generate-grid` | 2D and 3D |
| Polygon triangulation | `triangulate` | 2D |
| Remeshing pipeline proxy-application | `remesh` | 2D |
| Vertex smooth | `shift-vertices` | 2D |

Most algorithms work on 2D meshes because the structure was implemented first in 2D. Nonetheless,
the 3D structure is just as polished, and the 3D Delaunay triangulation was the most consequential
algorithm in our optimization process as it highlighted issues that did not appear in 2D.

Each binary has a documented CLI, which can be printed using the `--help` option. Outputs can be
serialized, and, if the `render` feature is enabled, the output mesh will be displayed at the end
of the execution.

## Delaunay triangulation

This is a 3D incremental Delaunay triangulation implementation. It roughly follows the algorithm
presented in _One machine, one minute, three billion tetrahedra_, Marot et al, 2019. We do not
implement boundary recovery, and focus on the benchmarking aspect by sampling point in a box-shaped
domain and inserting them into a first basic triangulation.

## Edge cut

This algorithm apply a basic edge cut operation to all edges of the mesh until a target length is
reached.

<figure style="text-align:center">
<img src="../images/cutedge-attributes.svg" alt="EdgeCut" width=100%/>
<figcaption><i>Edge cut operation. This can be applied to boundary edges, using only three new darts.</i></figcaption>
</figure>

## Overlay grid

### Intersection-based

This mesh generation algorithms uses intersection with an overlaid grid to create a triangular mesh
of a geometry passed as input.

### Refinement-based

This mesh generation algorithms uses incremental refinement of an octree and its dualization to
create an hexahedral mesh of the input geometry.

## Parameterized grid generation

This is a grid generation algorithm for our structure, i.e., mesh instantiation with pre-definite
values representing a grid.

<figure style="text-align:center">
<img src="../images/grid-gen.svg" alt="GridIndexing" width=100%/>
<figcaption><i>Dart indexing logic in generated 2D grids. The same approach is applied to 3D grids.</i></figcaption>
</figure>

Elements of the grid can be indexed in a systematic manner. Thanks to this, we implemented an
efficient parallel version of this algorithm, as well as a GPU version which outperforms the
parallel CPU one. We use the [`cudarc`](https://github.com/chelsea0x3b/cudarc) crate to offload
the value generation to the GPU.

## Polygon triangulation

This algorithm allows triangulation of simple 2D polygon using one of two methods:
[ear-clipping](https://en.wikipedia.org/wiki/Polygon_triangulation#Ear_clipping_method) or
[fanning](https://en.wikipedia.org/wiki/Fan_triangulation). The binary triangulates the entire
mesh input, while `honeycomb-kernel` provides the routine call used to triangulate a single cell.

## Remeshing pipeline proxy-application

This algorithm is a proxy-application for very common remeshing workflow found in triangle or
tetrahedron meshing. Multiple meshing kernels are applied in a loop until a certain predicate is
satisfied, or for a given number of rounds.

<figure style="text-align:center">
<img src="../images/all-remesh-ops.svg" alt="GridIndexing" width=80%/>
<figcaption><i>Remeshing loop structure.</i></figcaption>
</figure>

## Vertex smooth

We implement two parameterized smoothing algorithm: Laplace smoothing and Taubin smoothing. A
current work in progress includes a GPU-based Jacobi smoother using a Rust-Kokkos interoperability
library.
5 changes: 2 additions & 3 deletions user-guide/src/dev-guide/contributing.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Contributing

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

Contributions are welcome and accepted as pull requests on [GitHub][GH]. Feel free to use issues
Expand Down Expand Up @@ -53,10 +50,12 @@ Note that a most of the code possess documentation, including private modules /
the complete documentation by using the following instructions:

```shell
# Book
mdbook serve --open user-guide/
```

```shell
# Rust API
cargo +nightly doc --all --all-features --no-deps --document-private-items
```

Expand Down
32 changes: 15 additions & 17 deletions user-guide/src/dev-guide/library.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
# Libraries

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

Several crates of this project are published on the registry _crates.io_: the main crate, **honeycomb** (not yet
published), as well as specialized crates **honeycomb-core**, **honeycomb-kernels**, and **honeycomb-render**.
The repository hosts four crates.


## honeycomb
Expand All @@ -21,6 +17,7 @@ the dependency using the git repository:
# [dependencies]
honeycomb = {
git = "https://github.com/LIHPC-Computational-Geometry/honeycomb"
# tag = "X.X.X"
}
```

Expand All @@ -32,7 +29,7 @@ The following features are available:

- a builder structure to handle map creation: `CMapBuilder`.
- 2D and 3D combinatorial maps, usable in concurrent contexts: `CMap2`/`CMap3`. this includes:
- all regular operations (sew, unsew, beta images, ...),
- all regular operations (sew, unsew, beta image accesses, ...),
- a custom embedding logic to associate vertices and attributes to darts.
- abstractions over attributes, to allow arbitrary items binding to the map using the
same embedding logic as vertices:
Expand All @@ -49,23 +46,24 @@ The following features are available:
**honeycomb-kernels** is a Rust crate that provides implementations of meshing kernels using the core crate's
combinatorial maps. These implementations have multiple purposes:

1. Writing code using n-maps from a user's perspective
1. Writing code using \\(N\\)-maps from a user's perspective
2. Covering a wide range of operations, with routines that are more topology-heavy / geometry-heavy / balanced
3. Stressing the data structure, to identify its advantages and its pitfalls in a meshing context
4. Testing for more unwanted behaviors / bugs

Explanations provided in this guide focus on the overall workflow of algorithms; Implementation-specific details and
hypothesis are listed in the documentation of the crate.

When discussing algorithms, explanations provided in this guide focus on the high-level workflow;
Implementation-specific details and hypothesis are kept to the documentation of the crate.

## honeycomb-render

**honeycomb-render** is a Rust crate that provides a simple visualization framework to allow the user to render their
combinatorial map. It is designed to be used directly in the code by reading data through a reference to the map (as
opposed to a binary that would read serialized data). This render tool can be used to quickly debug algorithm results
by looking at the resulting structure instead of reading hard-to-interpret numerical data.
**honeycomb-render** is a Rust crate that provides a simple visualization framework to allow the
user to render their combinatorial map. It is designed to be used directly in the code by reading
data through a reference to the map (as opposed to a binary that would read serialized data). This
render tool can be used to quickly debug algorithm results by looking at the resulting structure
instead of reading hard-to-interpret raw data.

Use the [exported functions](../../honeycomb_render/index.html) to render a given combinatorial map. **You may need
to run the program in `release` mode to render large maps**. All items used to build that tool are kept public to allow
users to customize the render logic (e.g. to render a specific attribute).
Use the [exported functions](../../honeycomb_render/index.html) to render a given combinatorial map.
**You may need to run the program in `release` mode to render large maps**. All items used to build
that tool are kept public to allow users to customize the render logic (e.g. to render a specific
attribute).

14 changes: 4 additions & 10 deletions user-guide/src/dev-guide/project-structure.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
# Project structure

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

The project root is organized using Cargo workspaces at the moment. This may change when other languages are
introduced to the project.

The [repository][GH] hosts both published crates (usable content) as well as complementary content such as benchmarks,
examples or this guide.
The project root is organized using Cargo workspaces. The [repository][GH] hosts both published
crates (libraries) as well as complementary content such as benchmarks, examples or this guide.

[GH]: https://github.com/LIHPC-Computational-Geometry/honeycomb

Expand All @@ -23,5 +17,5 @@ The following libraries are available:
The repository also hosts:

- The `applications` crate, which contains a collection of algorithms which are used as benchmarks
and/or examples
- This book's source files, available in the `user-guide` directory
and/or examples.
- This book's source files, available in the `user-guide` directory.
7 changes: 2 additions & 5 deletions user-guide/src/examples/attributes.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
# Generic attribute system

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

The `attributes` module of the core crate provides the necessary tools for to add custom attributes
to given orbits of the map. Each attribute should be uniquely typed (i.e. to type aliases) as the
maps' internal storages use `std::any::TypeId` for identification.
to given orbits of the map. Each attribute should be uniquely typed (i.e. no type aliases) as the
maps' internal storages use `std::any::TypeId` for identification.

An attribute struct should implement both `AttributeBind` and `AttributeUpdate`. It can then be
added to the map using the dedicated `CMapBuilder` method. This is showcased in n example below,
Expand Down
3 changes: 0 additions & 3 deletions user-guide/src/examples/serialization.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# (De)Serialization

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

Our crate implements two different serialization logics. We use a custom format for combinatorial
Expand Down
9 changes: 3 additions & 6 deletions user-guide/src/examples/smoothing.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
# Parallel Laplace smoothing

**This content has been copy-pasted from the previous guide. It is up-to-date but should be improved
at some point.**

---

In the following routine, we shift each vertex that's not on a boundary to the average of its
Expand All @@ -22,9 +19,9 @@ The main map structure, `CMap2`, can be edited in parallel using transactions to
correctness.

In the main computation loop, we use a transaction to ensure each new vertex value is computed from
the current neighbor's values. The errors generated by `read_vertex` and `write_vertex` are used to
(early) detect any changes to the data used in the transaction, here, the list of `neigh` vertices.
the current neighbor's values. The errors generated by `read_vertex_tx` and `write_vertex_tx` are
used to detect any changes to the data used in the transaction, here, the list of `neigh` vertices.

At the end of the transaction block, the commit routine will check again if any used data has been
At the end of the transaction block, the commit routine will check if any used data has been
altered. If not, results of the transaction will be validated and written to memory.

Loading
Loading